⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skl_mpg4_anl.cpp

📁 mpeg4编解码器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -