?? skl_mpg4_anl.cpp
字號:
for(int y=ym; y<=yM; y+=dy) { SKL_UINT32 Sad = C->MV_Bits_Cost(mv[0],y); if (Sad>=Best_Sad) continue; Sad += C->Metric(C->Src, C->Ref + y*C->BpS + mv[0], C->BpS); if (Sad<Best_Sad) { Best_Sad = Sad; mv[1] = y; } } } dx >>= 1; dy >>= 1; } while(dx!=0 && dy!=0); return C->Eval(mv); }static int MV_Search_Diamond(ME_MAP * const C){ C->Start_Search(); const SKL_UINT32 Best_Sad = C->Best_Sad;// fprintf( stderr, "search box: (%d,%d)->(%d,%d) around (%d,%d) [Sad=%d]\n", C->xm, C->ym, C->xM, C->yM, C->xo, C->yo, C->Best_Sad); SKL_ASSERT(*C->Get_Cached_Sad(C->Best_MV[0], C->Best_MV[1]) == Best_Sad); while(1) { int x = C->Best_MV[0]; int y = C->Best_MV[1]; if (x<C->xM && !(C->Dir&0x02)) C->Eval_Dir(x+1,y, 0x100); if (x>C->xm && !(C->Dir&0x01)) C->Eval_Dir(x-1,y, 0x200); if (y<C->yM && !(C->Dir&0x08)) C->Eval_Dir(x, y+1,0x400); if (y>C->ym && !(C->Dir&0x04)) C->Eval_Dir(x, y-1,0x800); if (C->Dir&0xf00) // check corners now, if something was found { x = C->Best_MV[0]; y = C->Best_MV[1]; if (C->Dir&0x300) { if (y<C->yM) C->Eval_Dir(x, y+1,0x400); if (y>C->ym) C->Eval_Dir(x, y-1,0x800); } else { if (x<C->xM) C->Eval_Dir(x+1, y,0x100); if (x>C->xm) C->Eval_Dir(x-1, y,0x200); } C->Dir >>= 8; } else break; }// fprintf( stderr, "found:%d,%d\n", C->Best_MV[0],C->Best_MV[1]); return (C->Best_Sad<Best_Sad);}static int MV_Search_Square(ME_MAP * const C){ C->Start_Search(); const SKL_UINT32 Best_Sad = C->Best_Sad; SKL_ASSERT(*C->Get_Cached_Sad(C->Best_MV[0], C->Best_MV[1]) == Best_Sad); while(1) { int x = C->Best_MV[0]; int y = C->Best_MV[1]; if (!(C->Dir&0x02) && x<C->xM) C->Eval_Dir(x+1,y, 0x100); if (!(C->Dir&0x01) && x>C->xm) C->Eval_Dir(x-1,y, 0x200); if (!(C->Dir&0x08) && y<C->yM) C->Eval_Dir(x, y+1,0x400); if (!(C->Dir&0x04) && y>C->ym) C->Eval_Dir(x, y-1,0x800); if (x<C->xM) { if (y<C->yM) C->Eval_Dir(x+1, y+1,0x500); if (y>C->ym) C->Eval_Dir(x+1, y-1,0x900); } if (x>C->xm) { if (y<C->yM) C->Eval_Dir(x-1, y+1,0x600); if (y>C->ym) C->Eval_Dir(x-1, y-1,0xa00); } if (!(C->Dir & 0xf00)) break; C->Dir >>= 8; } return (C->Best_Sad<Best_Sad);}//////////////////////////////////////////////////////////static int MV_Search_Zero(ME_MAP * const C){ C->Best_Sad = C->Metric(C->Src,C->Ref,C->BpS); C->Best_MV[0] = 0; C->Best_MV[1] = 0; return 1;}static int MV_Search_Debug(ME_MAP * const C){#if 0 int dx = -C->Range; int dy = 0; if (dx<C->xm) dx = C->xm; else if (dx>C->xM) dx = C->xM; if (dy<C->ym) dy = C->ym; else if (dy>C->yM) dy = C->yM;#endif static int P = 0; int dx = P ? C->Range-1 : -C->Range; int dy = 0; P ^= 1; C->Best_Sad = C->Metric(C->Src, C->Ref+dx+dy*C->BpS, C->BpS); C->Best_MV[0] = dx; C->Best_MV[1] = dy; return 1;}//////////////////////////////////////////////////////////static SEARCH_MTHD MV_Searchs[] = { &MV_Search_Square, &MV_Search_Diamond, &MV_Search_PHODS, &MV_Search_Log, &MV_Search_Full, &MV_Search_Zero, &MV_Search_Debug};enum { MAX_SEARCH = 7 };//////////////////////////////////////////////////////////// class ME_MAP //////////////////////////////////////////////////////////void ME_MAP::Init(){ xo = 0; yo = 0; Src0 = Frame->Cur->Y; Ref0 = Frame->Past->Y; SKL_BZERO(Key_Map, sizeof(Key_Map)); Scratch1 = (SKL_BYTE*)Src0 - 16 - 16*BpS; Scratch2 = Scratch1 + 16;// Hit = 0; Miss = 0;}inline void ME_MAP::Set_Sub_Offset(const int dx, const int dy){ // Predictor should be set before getting here const int x = xo+dx, y = yo+dy; Ref = Ref0 + (x + y*BpS); Src = Src0 + (x + y*BpS); if (-Range<-16-x) xm = -15-x; else xm = -Range+1; if (-Range<-16-y) ym = -15-y; else ym = -Range+1; if (Range>Frame->Width-x) xM = Frame->Width-1 -x; else xM = Range-1; if (Range>Frame->Height-y) yM = Frame->Height-1-y; else yM = Range-1;// SKL_ASSERT(xm<=0 && xM>=0 || ym<=0 || yM>=0); xm_Sub = ((xm-1)<<Sub_Prec_Shift) + 1; xM_Sub = ((xM+1)<<Sub_Prec_Shift) - 1; ym_Sub = ((ym-1)<<Sub_Prec_Shift) + 1; yM_Sub = ((yM+1)<<Sub_Prec_Shift) - 1;}void ME_MAP::New_Scanline(int y){ yo = y; xo = 0;}SKL_UINT32 ME_MAP::Start(const METRIC metric, const METRIC_AVRG metric_Avrg){ New_Map(); Set_Sub_Offset(0,0); Metric = metric; Metric_Avrg = metric_Avrg; return Metric(Src,Ref,BpS);}int ME_MAP::Check_Limits(const SKL_MV mv, SKL_CST_STRING Label) const { const int Rng = Range << Sub_Prec_Shift; if (mv[0]<-Rng || mv[0]>=Rng || mv[1]<-Rng || mv[1]>=Rng) { if (Label!=0) fprintf( stderr, Label ); fprintf( stderr, "mv (%d,%d) has bad range (%d)!! ", mv[0], mv[1], Rng ); fprintf( stderr, "search box: (%d,%d)->(%d,%d) around (%d,%d)\n", xm, ym, xM, yM, xo, yo); return 0; } return 1;}int ME_MAP::Check_Frame_Limits(const SKL_MV mv, SKL_CST_STRING Label) const { int x = ( (xo<<Sub_Prec_Shift) + mv[0] ) >> Sub_Prec_Shift; int y = ( (yo<<Sub_Prec_Shift) + mv[1] ) >> Sub_Prec_Shift; if (x<-16 || x>=Frame->Width || y<-16 || y>=Frame->Height) { fprintf( stderr, "final displacement (%d,%d)=(%d,%d)+(%d,%d) is outside frame (%d,%d)! (predictor?)\n", x,y, xo,yo, mv[0], mv[1], Frame->Width, Frame->Height ); return 0; } return 1;}//////////////////////////////////////////////////////////// Field/Frame evaluation//////////////////////////////////////////////////////////static SKL_UINT32 Get_Frame_SAD(const SKL_BYTE * const Src, const SKL_MP4_INFOS * const Info){ SKL_UINT32 SAD; const int BpS = Info->BpS; SAD = Info->Img_Dsp->SAD_16x7_Self(Src, BpS); SAD += Info->Img_Dsp->SAD_16x7_Self(Src+8*BpS, BpS); return SAD;}static SKL_UINT32 Get_Field_SAD(const SKL_BYTE *Src, const SKL_MP4_INFOS * const Info){ SKL_UINT32 SAD; const int BpS = Info->BpS; SAD = Info->Img_Dsp->SAD_16x7_Self(Src, 2*BpS); SAD += Info->Img_Dsp->SAD_16x7_Self(Src+BpS, 2*BpS); return SAD;}static int Field_DCT_Is_Better(const SKL_BYTE *Src, const SKL_MP4_INFOS * const Info){ return (Get_Field_SAD(Src,Info) < Get_Frame_SAD(Src,Info));}//////////////////////////////////////////////////////////// Sub-pixel interpolation (old and experimental)//////////////////////////////////////////////////////////#if 0// Find the best (assuming it exists!) SSE match position (a,b)// between two 16x16 blocks Cur0 and Ref0.// This implementation uses the SGAN algorithm of mine.static void Find_Min_SSE(int &a, int &b, const SKL_BYTE * Cur0, const SKL_BYTE * Ref0, const int BpS){ // we use a barycentric average of every // optima, in hope it will lead to an // overall good estimate. // TODO: search window should be 17x17 // since minima is located withing [-1,1[x[-1,1[ // range (not [0,1[x[0,1[)! (check bounds, too) int Num;// int Den; int Nb; // horizontal pass Nb = 0; Num = 0; //Den = 1; const SKL_BYTE *Cur = Cur0, *Ref = Ref0; for(int y=0; y<15; ++y) { int N = 0, D = 0; for(int x=0; x<15; ++x) { // boundary pb! // a = U.(U-V) / |U-V|^2 int UV = Ref[x+1] - Ref[x]; int U = Ref[x+1] - Cur[x]; D += UV*UV; N += U*UV; } Cur += BpS; Ref += BpS; if (D!=0) {// Num = (Num*D + N*Den);// Den = (Den*D); Num += (N<<8) / D; // 8b fixed point only? Nb++; } } if (Nb) { // TODO: clipping should be useless if the minimum has been well-bracketed a = 0xff - (Num/Nb); if (a<0x00) a = 0x00; else if (a>0xff) a = 0xff; } else a = 0; // vertical pass Nb = 0; Num = 0; // Den = 1; for(int x=0; x<15; ++x) { // boundary pb! int N = 0, D = 0; const SKL_BYTE *Cur = Cur0, *Ref = Ref0; for(int y=0; y<15; ++y) { // b = U.(U-V) / |U-V|^2 int UV = Ref[x+BpS] - Ref[x]; int U = Ref[x+BpS] - Cur[x]; D += UV*UV; N += U*UV; Cur += BpS; Ref += BpS; } if (D!=0) { Num += (N<<8) / D; Nb++; } } if (Nb) { b = 0xff - (Num/Nb); if (b<0x00) b = 0x00; else if (b>0xff) b = 0xff; } else b = 0;}#endif#define SRND(x) (((x)+0x80)>>8)#if 0void ME_MAP::Refine_MV(SKL_MV MV, const int Prec, const int Rounding){ if (Prec>0) { int H, V; const SKL_BYTE *Rf = Ref + Best_MV[0] + Best_MV[1]*BpS; // input MV is FULL pel Find_Min_SSE(H, V, Rf, Src, BpS); if (Prec==1) { MV[0] = (Best_MV[0]<<1) + SRND(H); MV[1] = (Best_MV[1]<<1) + SRND(V); } else { // qpel MV[0] = (Best_MV[0]<<2) + SRND(2*H); MV[1] = (Best_MV[1]<<2) + SRND(2*V); }// printf( "%d,%d -> %d %d\n", Best_MV[0]<<1, Best_MV[1]<<1, MV[0], MV[1] ); } else { MV[0] = Best_MV[0]<<1; MV[1] = Best_MV[1]<<1; }}#endif//////////////////////////////////////////////////////////// refinement sub-searches#define SKL_AUTO_INCLUDE // shameless copy-paste from skl_mpg4i.h. TODO: BAD.static void Predict_16x16_QP(SKL_BYTE * const Dst, const SKL_BYTE *Src, SKL_BYTE * const YTmp, // <- 17x16 buffer const int x, const int y, const int BpS, const SKL_MB_FUNCS * const Ops){ const int Quads = (x&3) | ((y&3)<<2); Src += (y>>2)*BpS + (x>>2); switch(Quads) { default: case 0: Ops->HP_16x8[0](Dst, Src, BpS); Ops->HP_16x8[0](Dst+8*BpS, Src+8*BpS, BpS); break; case 1: Ops->H_Pass_Avrg(Dst, Src, 16, BpS); break; case 2: Ops->H_Pass(Dst, Src, 16, BpS); break; case 3: Ops->H_Pass_Avrg_Up(Dst, Src, 16, BpS); break; case 4: Ops->V_Pass_Avrg(Dst, Src, 16, BpS); break; case 5: Ops->H_LowPass_Avrg(YTmp, Src, 17, BpS); Ops->V_Pass_Avrg(Dst, YTmp, 16, BpS); break; case 6: Ops->H_LowPass(YTmp, Src, 17, BpS); Ops->V_Pass_Avrg(Dst, YTmp, 16, BpS); break; case 7: Ops->H_LowPass_Avrg_Up(YTmp, Src, 17, BpS); Ops->V_Pass_Avrg(Dst, YTmp, 16, BpS); break; case 8: Ops->V_Pass(Dst, Src, 16, BpS); break; case 9: Ops->H_LowPass_Avrg(YTmp, Src, 17, BpS); Ops->V_Pass(Dst, YTmp, 16, BpS); break; case 10: Ops->H_LowPass(YTmp, Src, 17, BpS); Ops->V_Pass(Dst, YTmp, 16, BpS); break; case 11: Ops->H_LowPass_Avrg_Up(YTmp, Src, 17, BpS); Ops->V_Pass(Dst, YTmp, 16, BpS); break; case 12: Ops->V_Pass_Avrg_Up(Dst, Src, 16, BpS); break; case 13: Ops->H_LowPass_Avrg(YTmp, Src, 17, BpS); Ops->V_Pass_Avrg_Up(Dst, YTmp, 16, BpS); break; case 14: Ops->H_LowPass(YTmp, Src, 17, BpS); Ops->V_Pass_Avrg_Up( Dst, YTmp, 16, BpS); break; case 15: Ops->H_LowPass_Avrg_Up(YTmp, Src, 17, BpS); Ops->V_Pass_Avrg_Up(Dst, YTmp, 16, BpS); break; }}static void Predict_16x8_Field_QP(SKL_BYTE * const Dst, const SKL_BYTE *Src, SKL_BYTE * const YTmp, // <- 9x16 buffer const int x, const int y, const int BpS, const SKL_MB_FUNCS * const Ops){ const int Quads = (x&3) | ((y&3)<<2); Src += ((y>>1)&~1)*BpS + (x>>2); switch(Quads) { default: case 0: Ops->HP_16x8[0](Dst, Src, 2*BpS); break; case 1: Ops->H_Pass_Avrg(Dst, Src, 8, 2*BpS); break; case 2: Ops->H_Pass(Dst, Src, 8, 2*BpS); break; case 3: Ops->H_Pass_Avrg_Up(Dst, Src, 8, 2*BpS); break; case 4: Ops->V_Pass_Avrg_8(Dst, Src, 16, 2*BpS); break; case 5: Ops->H_Pass_Avrg(YTmp, Src, 9, 2*BpS); Ops->V_Pass_Avrg_8(Dst, YTmp, 16, 2*BpS); break; case 6: Ops->H_Pass(YTmp, Src, 9, 2*BpS); Ops->V_Pass_Avrg_8(Dst, YTmp, 16, 2*BpS); break; case 7: Ops->H_Pass_Avrg_Up(YTmp, Src, 9, 2*BpS); Ops->V_Pass_Avrg_8(Dst, YTmp, 16, 2*BpS); break;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -