timgfilterpostproc.cpp
来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C++ 代码 · 共 1,961 行 · 第 1/5 页
CPP
1,961 行
const uint8_t TimgFilterPostprocSpp::offset[127][2]=
{
{0,0},
{0,0}, {4,4},
{0,0}, {2,2}, {6,4}, {4,6},
{0,0}, {5,1}, {2,2}, {7,3}, {4,4}, {1,5}, {6,6}, {3,7},
{0,0}, {4,0}, {1,1}, {5,1}, {3,2}, {7,2}, {2,3}, {6,3},
{0,4}, {4,4}, {1,5}, {5,5}, {3,6}, {7,6}, {2,7}, {6,7},
{0,0}, {0,2}, {0,4}, {0,6}, {1,1}, {1,3}, {1,5}, {1,7},
{2,0}, {2,2}, {2,4}, {2,6}, {3,1}, {3,3}, {3,5}, {3,7},
{4,0}, {4,2}, {4,4}, {4,6}, {5,1}, {5,3}, {5,5}, {5,7},
{6,0}, {6,2}, {6,4}, {6,6}, {7,1}, {7,3}, {7,5}, {7,7},
{0,0}, {4,4}, {0,4}, {4,0}, {2,2}, {6,6}, {2,6}, {6,2},
{0,2}, {4,6}, {0,6}, {4,2}, {2,0}, {6,4}, {2,4}, {6,0},
{1,1}, {5,5}, {1,5}, {5,1}, {3,3}, {7,7}, {3,7}, {7,3},
{1,3}, {5,7}, {1,7}, {5,3}, {3,1}, {7,5}, {3,5}, {7,1},
{0,1}, {4,5}, {0,5}, {4,1}, {2,3}, {6,7}, {2,7}, {6,3},
{0,3}, {4,7}, {0,7}, {4,3}, {2,1}, {6,5}, {2,5}, {6,1},
{1,0}, {5,4}, {1,4}, {5,0}, {3,2}, {7,6}, {3,6}, {7,2},
{1,2}, {5,6}, {1,6}, {5,2}, {3,0}, {7,4}, {3,4}, {7,0},
};
inline void TimgFilterPostprocSpp::add_block(int16_t *dst, int stride, DCTELEM block[64])
{
for (int y=0;y<8;y++)
{
paddw(*(__m64*)&dst[0+y*stride],*(__m64*)&block[0+y*8]);
paddw(*(__m64*)&dst[4+y*stride],*(__m64*)&block[4+y*8]);
}
}
inline void TimgFilterPostprocSpp::get_pixels(DCTELEM *block, const uint8_t *pixels, int line_size)
{
__m64 mm7=_mm_setzero_si64(),mm0,mm2,mm1,mm3;
for (int REG_a=-64;REG_a;pixels+=2*line_size,REG_a+=16)
{
movq (mm0,pixels);
movq (mm2,pixels+line_size);
movq (mm1,mm0);
movq (mm3,mm2);
punpcklbw (mm0,mm7);
punpckhbw (mm1,mm7);
punpcklbw (mm2,mm7);
punpckhbw (mm3,mm7);
movq ( 0+block+64+REG_a,mm0);
movq ( 4+block+64+REG_a,mm1);
movq ( 8+block+64+REG_a,mm2);
movq (12+block+64+REG_a,mm3);
}
}
#ifndef WIN64
void TimgFilterPostprocSpp::filter(uint8_t *dst, const uint8_t *src0, int dst_stride, int src_stride, unsigned int width, unsigned int height, const int8_t *qp_store, int qp_stride, bool is_luma)
{
const int count=1<<currentq;
const int stride=is_luma?temp_stride:((width+16+15)&(~15));
uint64_t block_align1[32*2],*block_align=(uint64_t*)(((intptr_t)block_align1+16)&(~15));
DCTELEM *block =(DCTELEM *)block_align;
DCTELEM *block2=(DCTELEM *)(block_align+16);
unsigned int y;
for (y=0;y<height;y++)
{
int index=8+8*stride+y*stride;
memcpy(src+index,src0+y*src_stride,width);
for(unsigned int x=0;x<8;x++)
{
src[index -x-1]=src[index+ x ];
src[index+width+x ]=src[index+width-x-1];
}
}
for (y=0;y<8;y++)
{
memcpy(src+( 7-y)*stride,src+( y+8)*stride,stride);
memcpy(src+(height+8+y)*stride,src+(height-y+7)*stride,stride);
}
//FIXME (try edge emu)
for (y=0;y<height+8;y+=8)
{
memset(temp+(8+y)*stride,0,8*stride*sizeof(int16_t));
for (unsigned int x=0;x<width+8;x+=8)
{
const int qps=3+is_luma;
int qp;
qp=qp_store[(std::min(x,width-1)>>qps)+(std::min(y,height-1)>>qps)*qp_stride];
//if(p->mpeg2) qp>>=1;
for (int i=0;i<count;i++)
{
const int x1=x+offset[i+count-1][0];
const int y1=y+offset[i+count-1][1];
const int index= x1 + y1*stride;
get_pixels(block,src+index,stride);
ff_fdct_mmx2(block);
//dsp->fdct(block);
requantize(block2,block,qp);
simple_idct_mmx_P(block2);
//dsp->idct(block2);
add_block(temp+index,stride,block2);
}
}
if (y)
store_slice(dst+(y-8)*dst_stride,temp+8+y*stride,dst_stride,stride,width,std::min(8U,height+8-y),6-currentq);
}
}
#endif
bool TimgFilterPostprocSpp::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TpostprocSettings *cfg=(const TpostprocSettings*)cfg0;
if (super::is(pict,cfg) && cfg->qual)
{
Trect r=pict.getRect(cfg->full,cfg->half);
return pictRect.dx>=16 && pictRect.dy>=16;
}
else
return false;
}
HRESULT TimgFilterPostprocSpp::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
const TpostprocSettings *cfg=(const TpostprocSettings*)cfg0;
#ifndef WIN64
if (prepare(cfg,31,pict.frametype) && currentq)
{
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 || old_sppMode!=cfg->sppMode)
{
old_sppMode=cfg->sppMode;
done();
}
if (!temp)
{
switch (cfg->sppMode)
{
case 0:requantize=hardthresh_mmx;break;
case 1:requantize=softthresh_mmx;break;
}
#ifdef __SSE2__
if (Tconfig::cpu_flags&FF_CPU_SSE2)
store_slice=TstoreSlice<Tsse2>::store_slice;
else
#endif
if (Tconfig::cpu_flags&FF_CPU_MMX)
store_slice=TstoreSlice<Tmmx>::store_slice;
else
store_slice=store_slice_c;
unsigned int h=(dy1[0]+16+15)&(~15);
temp_stride=(dx1[0]+16+15)&(~15);
temp=(int16_t*)aligned_malloc(temp_stride*h*sizeof(int16_t));
src=(uint8_t*)aligned_malloc(temp_stride*h*sizeof(uint8_t));
}
for (unsigned int i=0;i<pict.cspInfo.numPlanes;i++)
filter(tempPict2[i],tempPict1[i],stride2[i],stride1[i],dx1[i],dy1[i],quants,quantsDx,i==0);
if (Tconfig::cpu_flags&FF_CPU_MMX) _mm_empty();
if (Tconfig::cpu_flags&FF_CPU_MMXEXT) _mm_sfence();
}
}
#endif
return parent->deliverSample(++it,pict);
}
//============================== TimgFilterPostprocNic ===============================
// postprocessing routines by Nic (http://nic.dnsalias.com/)
TimgFilterPostprocNic::TimgFilterPostprocNic(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilterPostprocBase(Ideci,Iparent,false)
{
nic_dering=getNic_dering();
}
bool TimgFilterPostprocNic::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TpostprocSettings *cfg=(const TpostprocSettings*)cfg0;
if (super::is(pict,cfg) && Tlibmplayer::getPPmode(cfg,cfg->qual)&~(LUM_LEVEL_FIX|CHROM_LEVEL_FIX))
{
Trect r=pict.getRect(cfg->full,cfg->half);
return pictRect.dx>=16 && pictRect.dy>=16;
}
else
return false;
}
HRESULT TimgFilterPostprocNic::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
const TpostprocSettings *cfg=(const TpostprocSettings*)cfg0;
if (int ppmode=prepare(cfg,31,pict.frametype))
{
init(pict,cfg->full,cfg->half);
if (pictRect.dx>=16 && pictRect.dy>=16)
{
unsigned char *tempPict[4];
getCurNext(/*FF_CSPS_MASK_YUV_PLANAR*/FF_CSP_420P,pict,cfg->full,COPYMODE_DEF,tempPict);
nic_postprocess(tempPict,stride2,
pict.cspInfo.shiftX[1],pict.cspInfo.shiftY[1],
dx1[0],dy1[0],
quants,quantsDx,ppmode,cfg->nicXthresh,cfg->nicYthresh);
if (ppmode&LUM_DERING)
nic_dering(tempPict[0],dx1[0],dy1[0],stride2[0],quants,quantsDx,pict.cspInfo.shiftX[0],pict.cspInfo.shiftY[0]);
if (ppmode&CHROM_DERING)
{
nic_dering(tempPict[1],dx1[1],dy1[1],stride2[1],quants,quantsDx,pict.cspInfo.shiftX[1],pict.cspInfo.shiftY[1]);
nic_dering(tempPict[2],dx1[2],dy1[2],stride2[2],quants,quantsDx,pict.cspInfo.shiftX[2],pict.cspInfo.shiftY[2]);
}
}
}
return parent->deliverSample(++it,pict);
}
//============================ TimgFilterPostprocFspp ===============================
void TimgFilterPostprocFspp::filter(uint8_t *dst, const uint8_t *src0,
stride_t dst_stride, stride_t src_stride,
int width, int height,
int8_t *qp_store, int qp_stride, int is_luma)
{
int x, x0, y, es, qy, t;
const int stride= is_luma ? temp_stride : (width+16);//((width+16+15)&(~15))
const int step=6-log2_count;
const int qps= 3 + is_luma;
int32_t __attribute__((aligned(32))) block_align[4*8*BLOCKSZ+ 4*8*BLOCKSZ];
DCTELEM *block= (DCTELEM *)block_align;
DCTELEM *block3=(DCTELEM *)(block_align+4*8*BLOCKSZ);
memset(block3, 0, 4*8*BLOCKSZ);
//src=src-src_stride*8-8;//!
if (!src0 || !dst) return; // HACK avoid crash for Y8 colourspace
for(y=0; y<height; y++){
int index= 8 + 8*stride + y*stride;
memcpy(src + index, src0 + y*src_stride, width);//this line can be avoided by using DR & user fr.buffers
for(x=0; x<8; x++){
src[index - x - 1]= src[index + x ];
src[index + width + x ]= src[index + width - x - 1];
}
}
for(y=0; y<8; y++){
memcpy(src + ( 7-y)*stride, src + ( y+8)*stride, stride);
memcpy(src + (height+8+y)*stride, src + (height-y+7)*stride, stride);
}
//FIXME (try edge emu)
for(y=8; y<24; y++)
memset(temp+ 8 +y*stride, 0,width*sizeof(int16_t));
for(y=step; y<height+8; y+=step){ //step= 1,2
qy=y-4;
if (qy>height-1) qy=height-1;
if (qy<0) qy=0;
qy=(qy>>qps)*qp_stride;
row_fdct_s(block, src + y*stride +2-(y&1), stride, 2);
for(x0=0; x0<width+8-8*(BLOCKSZ-1); x0+=8*(BLOCKSZ-1)){
row_fdct_s(block+8*8, src + y*stride+8+x0 +2-(y&1), stride, 2*(BLOCKSZ-1));
if(qp)
column_fidct_s((int16_t*)(&threshold_mtx[0]), block+0*8, block3+0*8, 8*(BLOCKSZ-1)); //yes, this is a HOTSPOT
else
for (x=0; x<8*(BLOCKSZ-1); x+=8) {
t=x+x0-2; //correct t=x+x0-2-(y&1), but its the same
if (t<0) t=0;//t always < width-2
t=qp_store[qy+(t>>qps)];
//if(mpeg2) t>>=1; //copy mpeg2,prev_q to locals?
if (t!=prev_q) prev_q=t, mul_thrmat_s(t);
column_fidct_s((int16_t*)(&threshold_mtx[0]), block+x*8, block3+x*8, 8); //yes, this is a HOTSPOT
}
row_idct_s(block3+0*8, temp + (y&15)*stride+x0+2-(y&1), stride, 2*(BLOCKSZ-1));
memcpy(block, block+(BLOCKSZ-1)*64, 8*8*sizeof(DCTELEM)); //cycling
memcpy(block3, block3+(BLOCKSZ-1)*64, 6*8*sizeof(DCTELEM));
}
//
es=width+8-x0; // 8, ...
if (es>8)
row_fdct_s(block+8*8, src + y*stride+8+x0 +2-(y&1), stride, (es-4)>>2);
column_fidct_s((int16_t*)(&threshold_mtx[0]), block, block3, es-0);
row_idct_s(block3+0*8, temp + (y&15)*stride+x0+2-(y&1), stride, es>>2);
{const int y1=y-8+step;//l5-7 l4-6
if (!(y1&7) && y1) {
if (y1&8) store_slice_s(dst + (y1-8)*dst_stride, temp+ 8 +8*stride,
dst_stride, stride, width, 8, 5-log2_count);
else store_slice2_s(dst + (y1-8)*dst_stride, temp+ 8 +0*stride,
dst_stride, stride, width, 8, 5-log2_count);
} }
}
if (y&7) { // == height & 7
if (y&8) store_slice_s(dst + ((y-8)&~7)*dst_stride, temp+ 8 +8*stride,
dst_stride, stride, width, y&7, 5-log2_count);
else store_slice2_s(dst + ((y-8)&~7)*dst_stride, temp+ 8 +0*stride,
dst_stride, stride, width, y&7, 5-log2_count);
}
}
//This func reads from 1 slice, 1 and clears 0 & 1
void TimgFilterPostprocFspp::store_slice_s(uint8_t *dst, int16_t *src_, stride_t dst_stride, stride_t src_stride, long width, long height, long log2_scale)
{
uint8_t *src=(uint8_t*)src_;
const uint8_t *od=&TimgFilterPostprocSpp::TstoreSlice<Tmmx>::dither[0][0];
const uint8_t *end=&TimgFilterPostprocSpp::TstoreSlice<Tmmx>::dither[height][0];
width = (width+7)&~7;
dst_stride-=width;
//src_stride=(src_stride-width)*2;
int REG_d_=log2_scale;
uint8_t *REG_S=src;
uint8_t *REG_D=dst;
stride_t REG_a=src_stride;
__m64 mm5;
csimd::movd( REG_d_, mm5 );
REG_d_^=-1;
stride_t REG_c=REG_a;
REG_d_+=7;
REG_a=-REG_a;
REG_c-=width;
REG_c+= REG_c;
__m64 mm2;
csimd::movd( REG_d_, mm2);
src_stride=REG_c;
const uint8_t *REG_d=od;
REG_a<<=4;
__m64 mm3,mm4,mm7,mm0,mm1;
label2:
csimd::movq (REG_d, mm3);
csimd::movq (mm3, mm4 );
csimd::pxor (mm7, mm7);
csimd::punpcklbw( mm7, mm3 );
csimd::punpckhbw( mm7, mm4);
REG_c=width;
csimd::psraw (mm5, mm3);
csimd::psraw (mm5, mm4);
label1:
csimd::movq (mm7, REG_S+REG_a);
csimd::movq (REG_S, mm0 );
csimd::movq (8+REG_S, mm1);
csimd::movq (mm7, 8+REG_S+REG_a);
csimd::paddw (mm3, mm0);
csimd::paddw (mm4, mm1);
csimd::movq (mm7, REG_S);
csimd::psraw (mm2, mm0);
csimd::psraw (mm2, mm1);
csimd::movq (mm7, 8+REG_S);
csimd::packuswb (mm1, mm0);
REG_S+=16;
csimd::movq (mm0, REG_D);
REG_D+=8;
REG_c-=8;
if (REG_c>0) //jg
goto label1;//1b
REG_S+=src_stride;
REG_d+=8;
REG_D+=dst_stride;
if (end>REG_d)// cmp end, REG_d
goto label2;//jl 2b
}
//This func reads from 2 slices, 0 & 2 and clears 2-nd
void TimgFilterPostprocFspp::store_slice2_s(uint8_t *dst, int16_t *src_, stride_t dst_stride, stride_t src_stride, long width, long height, long log2_scale)
{
uint8_t *src=(uint8_t*)src_;
const uint8_t *od=&TimgFilterPostprocSpp::TstoreSlice<Tmmx>::dither[0][0];
const uint8_t *end=&TimgFilterPostprocSpp::TstoreSlice<Tmmx>::dither[height][0];
width = (width+7)&~7;
dst_stride-=width;
//src_stride=(src_stride-width)*2;
int REG_d_= log2_scale;
uint8_t*REG_S= src;
uint8_t*REG_D= dst;
stride_t REG_a= src_stride;
__m64 mm5;
csimd::movd( REG_d_, mm5);
REG_d_^=-1;
stride_t REG_c=REG_a;
REG_d_+=7;
REG_c-=width;
REG_c+=REG_c;
__m64 mm2;
csimd::movd (REG_d_, mm2);
src_stride=REG_c;
const uint8_t *REG_d= od;
REG_a<<=5;
__m64 mm3,mm4,mm7,mm0,mm1,mm6;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?