timgfilterpostproc.cpp
来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C++ 代码 · 共 1,961 行 · 第 1/5 页
CPP
1,961 行
/*
* 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 "TimgFilterPostproc.h"
#include "TpostprocSettings.h"
#include "Tlibmplayer.h"
#include "TvideoCodec.h"
#include "IffdshowBase.h"
#include "IffdshowDecVideo.h"
#include "Tconfig.h"
#include "nic/nic_postProcess.h"
#include "libavcodec/avcodec.h"
#include "ffdebug.h"
//============================== TimgFilterPostprocBase =============================
const unsigned int TimgFilterPostprocBase::quantsDx=128*2;
const unsigned int TimgFilterPostprocBase::quantsDy= 96*2;
TimgFilterPostprocBase::TimgFilterPostprocBase(IffdshowBase *Ideci,Tfilters *Iparent,bool Ih264):
TimgFilter(Ideci,Iparent),
h264(Ih264),testh264(true),oldh264mode(-1),
wasIP(false),
oldDeblockStrength(UINT_MAX),
quants((int8_t*)aligned_calloc(quantsDx,quantsDy))
{
}
TimgFilterPostprocBase::~TimgFilterPostprocBase()
{
aligned_free(quants);
}
bool TimgFilterPostprocBase::pp_codec(int CodecID)
{
if(raw_codec(CodecID))
return true;
switch (CodecID) {
case CODEC_ID_MPEG1VIDEO:
case CODEC_ID_MPEG2VIDEO:
case CODEC_ID_LIBMPEG2:
case CODEC_ID_MPEG4:
case CODEC_ID_MSMPEG4V1:
case CODEC_ID_MSMPEG4V2:
case CODEC_ID_MSMPEG4V3:
case CODEC_ID_H263:
case CODEC_ID_SVQ1:
case CODEC_ID_FLV1:
case CODEC_ID_INDEO2:
case CODEC_ID_INDEO3:
case CODEC_ID_XVID4:
case CODEC_ID_MJPEG:
case CODEC_ID_MJPEGB:
case CODEC_ID_MSVIDEO1:
case CODEC_ID_CINEPAK:
case CODEC_ID_VP5:
case CODEC_ID_VP6:
return true;
default: return false;
}
}
int TimgFilterPostprocBase::prepare(const TpostprocSettings *cfg,int maxquant,int frametype)
{
const TvideoCodecDec *movie=NULL;
if (!pp_codec(deci->getCurrentCodecId2()))
return 0;
currentq=0;
if (!cfg->isCustom && cfg->autoq && cfg->qual)
{
currentq=deci->getParam2(IDFF_currentq);
#if 1
int cpuusage=deci->getCpuUsageForPP();
#else
int64_t late;deciV->getLate(&late);
DPRINTF(_l("late:%I64i"),late);
int cpuusage=late>100*10000LL?91:0;
#endif
if (cpuusage>90 && deciV->getQueuedCount()<8)
{
if (currentq>0) currentq--;
}
else
{
if (currentq<cfg->qual) currentq++;
}
deci->putParam(IDFF_currentq,currentq);
}
else
deci->putParam(IDFF_currentq,currentq=cfg->qual);
//DPRINTF("currentq: %i",currentq);
int ppmode=Tlibmplayer::getPPmode(cfg,currentq);
if (!ppmode) return ppmode;
unsigned int deblockStrength=cfg->deblockStrength;
if (!movie) deciV->getMovieSource(&movie);
if (!movie || !movie->quants)
{
oldDeblockStrength=deblockStrength;
unsigned char *quant=(unsigned char *)quants;
for (unsigned int i=0;i<quantsDx*quantsDy;quant+=1,i++)
{
int q=((maxquant/2)*deblockStrength)>>8;
*quant=(unsigned char)limit(q,1,maxquant);
}
}
else
if (!wasIP || (frametype&FRAME_TYPE::typemask)!=FRAME_TYPE::B)
{
wasIP=true;
const unsigned char *quantsMovie=(const unsigned char*)movie->quants;
unsigned int quantsDxMovie=movie->quantsDx;
unsigned int quantsDyMovie=movie->quantsDy;
unsigned int quantsStrideMovie=movie->quantsStride;
unsigned int quantBytesMovie=movie->quantBytes;
int8_t *quants2=quants;
for (unsigned int y=0;y<quantsDyMovie;quantsMovie+=quantBytesMovie*quantsStrideMovie,quants2+=quantsDx,y++)
{
const unsigned char *quantsMovieln=quantsMovie;
int8_t *quants2ln=quants2;
for (unsigned int x=0;x<quantsDxMovie;quantsMovieln+=quantBytesMovie,quants2ln++,x++)
{
int q=(*quantsMovieln*deblockStrength)>>8;
if (movie->quantType==FF_QSCALE_TYPE_MPEG2) q>>=1;
*quants2ln=(unsigned char)limit(q,1,maxquant);
}
}
}
return ppmode;
}
void TimgFilterPostprocBase::onSeek(void)
{
testh264=true;wasIP=false;
}
//============================ TimgFilterPostprocMplayer ============================
TimgFilterPostprocMplayer::TimgFilterPostprocMplayer(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilterPostprocBase(Ideci,Iparent,false)
{
libmplayer=NULL;
pp_ctx=NULL;Tlibmplayer::pp_mode_defaults(pp_mode);
}
TimgFilterPostprocMplayer::~TimgFilterPostprocMplayer()
{
if (libmplayer) libmplayer->Release();
}
void TimgFilterPostprocMplayer::done(void)
{
if (pp_ctx) libmplayer->pp_free_context(pp_ctx);pp_ctx=NULL;
}
void TimgFilterPostprocMplayer::onSizeChange(void)
{
done();
}
bool TimgFilterPostprocMplayer::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TpostprocSettings *cfg=(const TpostprocSettings*)cfg0;
if (super::is(pict,cfg) && Tlibmplayer::getPPmode(cfg,cfg->qual))
{
Trect r=pict.getRect(cfg->full,cfg->half);
return pictRect.dx>=16 && pictRect.dy>=16;
}
else
return false;
}
HRESULT TimgFilterPostprocMplayer::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
const TpostprocSettings *cfg=(const TpostprocSettings*)cfg0;
if (int ppmode=prepare(cfg,31,0))
{
init(pict,cfg->full,cfg->half);
if (pictRect.dx>=16 && pictRect.dy>=16)
{
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));
}
pp_mode.lumMode=ppmode&15;
pp_mode.chromMode=(ppmode>>4)&15;
if (cfg->deblockMplayerAccurate)
{
pp_mode.baseDcDiff=128;
pp_mode.flatnessThreshold=7;
if (pp_mode.lumMode&H_DEBLOCK) pp_mode.lumMode=(pp_mode.lumMode&~H_DEBLOCK)|H_A_DEBLOCK;
if (pp_mode.lumMode&V_DEBLOCK) pp_mode.lumMode=(pp_mode.lumMode&~V_DEBLOCK)|V_A_DEBLOCK;
if (pp_mode.chromMode&H_DEBLOCK) pp_mode.chromMode=(pp_mode.chromMode&~H_DEBLOCK)|H_A_DEBLOCK;
if (pp_mode.chromMode&V_DEBLOCK) pp_mode.chromMode=(pp_mode.chromMode&~V_DEBLOCK)|V_A_DEBLOCK;
}
else
{
pp_mode.baseDcDiff=256/8;
pp_mode.flatnessThreshold=56-16-1;
}
if (pp_mode.lumMode&LUM_LEVEL_FIX && cfg->fullYrange)
{
pp_mode.minAllowedY=0;
pp_mode.maxAllowedY=255;
}
else
{
pp_mode.minAllowedY=16;
pp_mode.maxAllowedY=234;
}
int frametype=pict.frametype&FRAME_TYPE::typemask; //3 = B
libmplayer->pp_postprocess(tempPict1,stride1,
tempPict2,stride2,
dx1[0],dy1[0],
quants,quantsDx,
&pp_mode,pp_ctx,frametype);
}
}
return parent->deliverSample(++it,pict);
}
//============================== TimgFilterPostprocSpp ===============================
#include "csimd.h"
extern "C" void simple_idct_mmx_P(short*);
void TimgFilterPostprocSpp::ff_fdct_mmx2(int16_t *block)
{
static const int BITS_FRW_ACC=3; //; 2 or 3 for accuracy
static const int SHIFT_FRW_COL=BITS_FRW_ACC;
static const int SHIFT_FRW_ROW=(BITS_FRW_ACC + 17 - 3);
static const int RND_FRW_ROW=(1 << (SHIFT_FRW_ROW-1));
static __align8(const int16_t,tab_frw_01234567[]) = { // forward_dct coeff table
16384, 16384, 22725, 19266,
16384, 16384, 12873, 4520,
21407, 8867, 19266, -4520,
-8867, -21407, -22725, -12873,
16384, -16384, 12873, -22725,
-16384, 16384, 4520, 19266,
8867, -21407, 4520, -12873,
21407, -8867, 19266, -22725,
22725, 22725, 31521, 26722,
22725, 22725, 17855, 6270,
29692, 12299, 26722, -6270,
-12299, -29692, -31521, -17855,
22725, -22725, 17855, -31521,
-22725, 22725, 6270, 26722,
12299, -29692, 6270, -17855,
29692, -12299, 26722, -31521,
21407, 21407, 29692, 25172,
21407, 21407, 16819, 5906,
27969, 11585, 25172, -5906,
-11585, -27969, -29692, -16819,
21407, -21407, 16819, -29692,
-21407, 21407, 5906, 25172,
11585, -27969, 5906, -16819,
27969, -11585, 25172, -29692,
19266, 19266, 26722, 22654,
19266, 19266, 15137, 5315,
25172, 10426, 22654, -5315,
-10426, -25172, -26722, -15137,
19266, -19266, 15137, -26722,
-19266, 19266, 5315, 22654,
10426, -25172, 5315, -15137,
25172, -10426, 22654, -26722,
16384, 16384, 22725, 19266,
16384, 16384, 12873, 4520,
21407, 8867, 19266, -4520,
-8867, -21407, -22725, -12873,
16384, -16384, 12873, -22725,
-16384, 16384, 4520, 19266,
8867, -21407, 4520, -12873,
21407, -8867, 19266, -22725,
19266, 19266, 26722, 22654,
19266, 19266, 15137, 5315,
25172, 10426, 22654, -5315,
-10426, -25172, -26722, -15137,
19266, -19266, 15137, -26722,
-19266, 19266, 5315, 22654,
10426, -25172, 5315, -15137,
25172, -10426, 22654, -26722,
21407, 21407, 29692, 25172,
21407, 21407, 16819, 5906,
27969, 11585, 25172, -5906,
-11585, -27969, -29692, -16819,
21407, -21407, 16819, -29692,
-21407, 21407, 5906, 25172,
11585, -27969, 5906, -16819,
27969, -11585, 25172, -29692,
22725, 22725, 31521, 26722,
22725, 22725, 17855, 6270,
29692, 12299, 26722, -6270,
-12299, -29692, -31521, -17855,
22725, -22725, 17855, -31521,
-22725, 22725, 6270, 26722,
12299, -29692, 6270, -17855,
29692, -12299, 26722, -31521,
};
static __align8(const int16_t,fdct_tg_all_16[]) = {
13036, 13036, 13036, 13036, // tg * (2<<16) + 0.5
27146, 27146, 27146, 27146, // tg * (2<<16) + 0.5
-21746, -21746, -21746, -21746, // tg * (2<<16) + 0.5
};
static const __int64 fdct_one_corr = 0x0001000100010001LL;
static __align8(const int16_t,ocos_4_16[4]) = {
23170, 23170, 23170, 23170, //cos * (2<<15) + 0.5
};
static __align8(const int32_t,fdct_r_row[2])={RND_FRW_ROW, RND_FRW_ROW };
struct Tcol
{
static __forceinline void fdct_col(const int16_t *in, int16_t *out, int offset)
{
__m64 mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7;
csimd::movq((in + offset + 1 * 8), mm0);
csimd::movq((in + offset + 6 * 8), mm1);
csimd::movq(mm0, mm2);
csimd::movq((in + offset + 2 * 8), mm3);
csimd::paddsw(mm1, mm0);
csimd::movq((in + offset + 5 * 8), mm4);
csimd::psllw(SHIFT_FRW_COL, mm0);
csimd::movq((in + offset + 0 * 8), mm5);
csimd::paddsw(mm3, mm4);
csimd::paddsw((in + offset + 7 * 8), mm5);
csimd::psllw(SHIFT_FRW_COL, mm4);
csimd::movq(mm0, mm6);
csimd::psubsw(mm1, mm2);
csimd::movq((fdct_tg_all_16 + 4), mm1);
csimd::psubsw(mm4, mm0);
csimd::movq((in + offset + 3 * 8), mm7);
csimd::pmulhw(mm0, mm1);
csimd::paddsw((in + offset + 4 * 8), mm7);
csimd::psllw(SHIFT_FRW_COL, mm5);
csimd::paddsw(mm4, mm6);
csimd::psllw(SHIFT_FRW_COL, mm7);
csimd::movq(mm5, mm4);
csimd::psubsw(mm7, mm5);
csimd::paddsw(mm5, mm1);
csimd::paddsw(mm7, mm4);
csimd::por(fdct_one_corr, mm1);
csimd::psllw(SHIFT_FRW_COL + 1, mm2);
csimd::pmulhw((fdct_tg_all_16 + 4), mm5);
csimd::movq(mm4, mm7);
csimd::psubsw((in + offset + 5 * 8), mm3);
csimd::psubsw(mm6, mm4);
csimd::movq(mm1, (out + offset + 2 * 8));
csimd::paddsw(mm6, mm7);
csimd::movq((in + offset + 3 * 8), mm1);
csimd::psllw(SHIFT_FRW_COL + 1, mm3);
csimd::psubsw((in + offset + 4 * 8), mm1);
csimd::movq(mm2, mm6);
csimd::movq(mm4, (out + offset + 4 * 8));
csimd::paddsw(mm3, mm2);
csimd::pmulhw(ocos_4_16, mm2);
csimd::psubsw(mm3, mm6);
csimd::pmulhw(ocos_4_16, mm6);
csimd::psubsw(mm0, mm5);
csimd::por(fdct_one_corr, mm5);
csimd::psllw(SHIFT_FRW_COL, mm1);
csimd::por(fdct_one_corr, mm2);
csimd::movq(mm1, mm4);
csimd::movq((in + offset + 0 * 8), mm3);
csimd::paddsw(mm6, mm1);
csimd::psubsw((in + offset + 7 * 8), mm3);
csimd::psubsw(mm6, mm4);
csimd::movq((fdct_tg_all_16 + 0), mm0);
csimd::psllw(SHIFT_FRW_COL, mm3);
csimd::movq((fdct_tg_all_16 + 8), mm6);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?