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

📄 skl_mpg4_anl.cpp

📁 mpeg4编解码器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
          Sad4_0 = Metric_8x8(Cursor.Src +     8*BpS, Rf,   BpS);          if (Sad4_0>=Sad_Sub_Limit) goto Go_4v;          Sad4_0 = Metric_8x8(Cursor.Src + 8 + 8*BpS, Rf+8, BpS);          if (Sad4_0>=Sad_Sub_Limit) goto Go_4v;          goto Done_4v;        }#endifGo_4v:        {          SKL_UINT32 Sad4, Sad16, Saved_Sad = Cursor.Best_Sad;          SKL_MV Saved_MV;          SKL_COPY_MV( Saved_MV, MVs[0] );          Cursor.Metric      = Metric_8x8;          Cursor.Metric_Avrg = Metric_8x8_Avrg;            // Cursor.Pred and Sub_Offset() are ok, here//          Cursor.Set_MV_Predictor(&MVs[0], MV_Stride, 0);          Sad16  = Cursor.Sub_Search(Map[0].MV, 0,0);          if (Use_HPels) Sad4  = Cursor.Refine_MV_HPels(MVs[0], Subpixel_Precision, Rounding, _HPels);          else           Sad4  = Cursor.Refine_MV_8x8(MVs[0], Subpixel_Precision, Rounding);          SKL_ASSERT(Cursor.Is_In_Range(MVs[0]));//          Set_Max(Maxs[1], MVs[0], Cursor.Pred);          Cursor.Set_MV_Predictor(&MVs[1], MV_Stride, 1, ABits);          Sad16 += Cursor.Sub_Search(Map[0].MV, 8,0);          if (Use_HPels) Sad4 += Cursor.Refine_MV_HPels(MVs[1], Subpixel_Precision, Rounding, _HPels);          else           Sad4 += Cursor.Refine_MV_8x8(MVs[1], Subpixel_Precision, Rounding);          SKL_ASSERT(Cursor.Is_In_Range(MVs[1]));//          Store_Max(Maxs[1], MVs[1], Cursor.Pred);          Cursor.Set_MV_Predictor(&MVs[MV_Stride+0], MV_Stride, 2, ABits);          Sad16 += Cursor.Sub_Search(Map[0].MV, 0,8);          if (Use_HPels) Sad4 += Cursor.Refine_MV_HPels(MVs[MV_Stride+0], Subpixel_Precision, Rounding, _HPels);          else           Sad4 += Cursor.Refine_MV_8x8(MVs[MV_Stride+0], Subpixel_Precision, Rounding);          SKL_ASSERT(Cursor.Is_In_Range(MVs[MV_Stride+0]));//          Store_Max(Maxs[1], MVs[MV_Stride+0], Cursor.Pred);          Cursor.Set_MV_Predictor(&MVs[MV_Stride+1], MV_Stride, 3, ABits);          Sad16 += Cursor.Sub_Search(Map[0].MV, 8,8);          if (Use_HPels) Sad4 += Cursor.Refine_MV_HPels(MVs[MV_Stride+1], Subpixel_Precision, Rounding, _HPels);          else           Sad4 += Cursor.Refine_MV_8x8(MVs[MV_Stride+1], Subpixel_Precision, Rounding);          SKL_ASSERT(Cursor.Is_In_Range(MVs[MV_Stride+1]));//          Store_Max(Maxs[1], MVs[MV_Stride+1], Cursor.Pred);//          printf( "Sad4=%d Sad4_FP=%d Sad16=%d  (%d,%d)\n", Sad4, Sad16, Saved_Sad, Map[0].MV[0],Map[0].MV[1]);          Sad4 += Sad4_Penalty;          if (Sad4<Saved_Sad)          {            Map->Type = SKL_MAP_8x8;            Map->Sad = Sad4;            Update_Map_Data(Map, pMap, Sad16, MVs[0]);//            Add_Max_MV_To_Stats(Maxs[1]);            Add_To_Stats(MVs[0]);            Add_To_Stats(MVs[1]);            Add_To_Stats(MVs[MV_Stride+0]);            Add_To_Stats(MVs[MV_Stride+1]);          }          else            SKL_COPY_MV( MVs[0], Saved_MV );  // wasn't worth...          Cursor.Set_Sub_Offset(0,0);          // Warning: Cursor.Pred, .IPred, .Best_MV, .Best_Sad, Src, Ref and .Metric* are trashed here        }      }Done_4v:      if (Map->Type==SKL_MAP_16x16) {Done_16x16://        Add_Max_MV_To_Stats(Maxs[0]);        Add_To_Stats(MVs[0]);        SKL_COPY_MV(MVs[          1], MVs[0]);        SKL_COPY_MV(MVs[MV_Stride+0], MVs[0]);        SKL_COPY_MV(MVs[MV_Stride+1], MVs[0]);      }Done:      if (Interlace_DCT>0)      {          /* note: for INTER blocks, we should decide field DCT *after* the              predictions has been formed, but we expect it to be equally as              good as working directly on unpredicted frame source. */        if (Interlace_DCT==2 || Field_DCT_Is_Better(Cursor.Src, Frame))          Map->Flags |= 1;      // -> use Field_DCT      }#if 0      Cursor.Check_Limits(MVs[0], "[post]:");      Cursor.Check_Limits(MVs[1], "[post]:");      Cursor.Check_Limits(MVs[MV_Stride+0], "[post]:");      Cursor.Check_Limits(MVs[MV_Stride+1], "[post]:");      Cursor.Check_Frame_Limits(MVs[0], "[flm]:");#endif      Map++;      MVs += 2;      if (pMVs!=0) {        pMVs += 2;        pMap++;      }      Cursor++;    }    MVs += 4 + MV_Stride;   // skip edge and next line    if (pMVs!=0) pMVs += 4 + MV_Stride;  }  Frame->Img_Dsp->Switch_Off();  Compile_Stats();    // Warning: this func uses floats. Call after EMMS.    // last 30% before reaching forced key-frame?    // => we artificially raise the perceived number of intras  int Scale = 100;  const int dCount = 30*Intra_Max - 100*Intra_Count;  if (dCount>0)    Scale += Scale*dCount/(30*Intra_Max);  if (Nb_Intras * Scale > Intra_Limit * Nb_Relevant)  {    Intra_Count = -1;  // real scene change//    printf( "Scene change! Nb:%d / %d  (/%d)  =>%.1f%%\n", Nb_Intras, Nb_Relevant, Frame->MB_W*Frame->MB_H, 100.f*Nb_Intras/Nb_Relevant);  }//  fprintf( stderr, "Miss:%d, Hit:%d (%.2f%%)\n", Cursor.Miss, Cursor.Hit, 100.f*Cursor.Hit/(Cursor.Miss+Cursor.Hit) );}////////////////////////////////////////////////////////////  GMC pass (experimental)//////////////////////////////////////////////////////////#define GMC_RND(x)  ( (x)<0. ? -(int)( -(x)+.5f ) : (int)( (x)+.5f ) )#define GMC_DBG(S)  // printf( S )void SKL_MP4_ANALYZER_I::Global_GMC_Pass(SKL_MP4_INFOS * const Frame){  GMC_Mode &= ~1;  if (Reduced_Frame>0)    return;    // no GMC in reduced resolution VOP  int Nb_Smpl, i, j;  const int MB_W = Frame->MB_W;  const int MB_H = Frame->MB_H;  const int MV_Up = 2*Frame->MV_Stride;  const int BpS   = Frame->BpS;  int (*Smpl)[2] = (int (*)[2]) alloca(MB_W*MB_H*2*sizeof(int));  SKL_BYTE *Scratch = (SKL_BYTE*) alloca(16*BpS);  SKL_MP4_MAP *Map;  SKL_MV *MVs;  SKL_UINT32 GMC_SAD_PENALTY;  // small mv penalty (that's the point of GMC!!)  SKL_UINT32 GMC_AUTO_SAD_LIMIT;  METRIC Metric_16x16;  METRIC_DEV Metric_Dev;  switch( Search_Metric ) {    case 2:      Metric_16x16 = Frame->Img_Dsp->Hadamard_SAD_16x16;      Metric_Dev   = Frame->Img_Dsp->Hadamard_Dev_16x16;      GMC_AUTO_SAD_LIMIT = 150;      GMC_SAD_PENALTY = 4;    break;    case 1:      Metric_16x16 = Frame->Img_Dsp->SSD_16x16;      Metric_Dev   = Frame->Img_Dsp->Sqr_Dev_16x16;      GMC_AUTO_SAD_LIMIT = 500;      GMC_SAD_PENALTY = 4;    break;    default:      Metric_16x16 = Frame->Img_Dsp->SAD_16x16;      Metric_Dev   = Frame->Img_Dsp->Abs_Dev_16x16;      GMC_AUTO_SAD_LIMIT = 700;      GMC_SAD_PENALTY = 4;    break;  }  const int LAPL_LIMIT  = 14;  float Scale = 1.f * (1<<(3-GMC_Accuracy));  if (Subpixel_Precision==2) Scale *= 0.5f;  Nb_Smpl = 0;  MVs = Frame->Cur->MV;  Map = Frame->Cur->Map;  for(j=0; j<MB_H; ++j) {    for(i=0; i<MB_W; ++i) {      if (Map[i].Type!=SKL_MAP_16x16 && Map[i].Type!=SKL_MAP_8x8)   // not INTRA or SKIPPED        { GMC_DBG( "." ); continue; }      const int vx0 = MVs[2*i][0];      const int vy0 = MVs[2*i][1];      int Lapl_x = 0, Lapl_y = 0;      if (i>0) {        Lapl_x += MVs[2*i-1][0] - vx0;        Lapl_y += MVs[2*i-1][1] - vy0;      }      if (i<MB_W-1) {        Lapl_x += MVs[2*i+1][0] - vx0;        Lapl_y += MVs[2*i+1][1] - vy0;      }      if (j>0) {        Lapl_x += MVs[2*i-Frame->MV_Stride][0] - vx0;        Lapl_y += MVs[2*i-Frame->MV_Stride][1] - vy0;      }      if (j<MB_H-1) {        Lapl_x += MVs[2*i+Frame->MV_Stride][0] - vx0;        Lapl_y += MVs[2*i+Frame->MV_Stride][1] - vy0;      }      if (ABS(Lapl_x)+ABS(Lapl_y)>LAPL_LIMIT)        { GMC_DBG( "-" ); continue; }      const SKL_BYTE * const Src = Frame->Cur->Y + i*16 + j*16*BpS;      SKL_UINT32 Sad;#if 1      Sad  = (i<MB_W-1) ? Metric_16x16(Src, Src+1, BpS) : Metric_16x16(Src, Src-1, BpS);      Sad += (j<MB_H-1) ? Metric_16x16(Src, Src+BpS, BpS) : Metric_16x16(Src, Src-BpS, BpS);#else      Sad =  Metric_Dev(Src, BpS);    // enough textured?#endif      if (Sad<GMC_AUTO_SAD_LIMIT) { GMC_DBG( "=" ); continue; }      Smpl[Nb_Smpl][0] = i;      Smpl[Nb_Smpl][1] = j;      Nb_Smpl++;      GMC_DBG( "*" );    }    GMC_DBG("\n");    MVs += MV_Up;    Map += MB_W;  }  GMC_DBG( "\n" );  Frame->Img_Dsp->Switch_Off();    // Note:    //    // We're about to least-square fit the 6-parameters model:    //    //    mvx(x,y) = vx0 + a.x + b.y    //    mvy(x,y) = vy0 + c.x + d.y    //    // that globally interpolates the motion vector (mvx,mvy) at point x,y.    // The unknowns are: vx0,vy0, a,b,c,d. The mapping toward the ISO warp    // points is pretty straightforward. We always use 3 warp points, leaving    // the task of simplifying the sprite motion to the SKL_GMC_DSP module.    //    // Now, minimizing the overall error E = < (vx-mvx)^2 + (vy-mvy)^2 >    // where (vx,vy) are the result of the previous ME pass, and filtering    // out the seemingly outliers, gives the set of equations:    //    //   vx0 = <vx> - a.<x> - b.<y>    //   vy0 = <vy> - c.<x> - d.<y>    //   {x.vx} = a.{xx} + b.{xy}    //   {y.vx} = a.{xy} + b.{yy}    //   {x.vy} = c.{xx} + d.{xy}    //   {y.vy} = c.{xy} + d.{yy}    //    // where <f> is the sampled average of quantity 'f', and {fg} is the     // deviates of f*g, that is: {fg} = <fg> - <f>.<g>.    // Inverting this system easily gives:    //    //   Det = {yy}.{xx} - {xy}.{xy}.    //   a = ( {x.vx}.{yy} - {y.vx}{xy} ) / Det    //   b = ( {y.vx}.{xx} - {x.vx}{xy} ) / Det    //   c = ( {x.vy}.{yy} - {y.vy}{xy} ) / Det    //   d = ( {y.vy}.{xx} - {x.vy}{xy} ) / Det    //    // with some special degenerate cases.    // Of course, vx0,vy0 are deduced after a,b,c,d are known.    //  float a=0.,b=0.,c=0.,d=0., vx0=0., vy0=0.;    // params  float W;  while(Nb_Smpl>=8)  {    a=0.; b=0.; c=0.; d=0.;    vx0=0.; vy0=0.;    W = 0.;    float x=0., y=0., Vx = 0., Vy=0.;           // stats    float xx=0., yy=0., xy=0.;    float xVx=0., yVx=0., xVy=0., yVy=0.;    Map = Frame->Cur->Map;     MVs = Frame->Cur->MV;    int n;    for(n=0; n<Nb_Smpl; ++n) {      i = Smpl[n][0]; j = Smpl[n][1];      const float xo = 16.f*i;      const float yo = 16.f*j;      const float vxo = (float)MVs[2*i+j*MV_Up][0];      const float vyo = (float)MVs[2*i+j*MV_Up][1];      SKL_ASSERT(Map[i + j*MB_W].Sad>0);      const float w = 1.f / Map[i + j*MB_W].Sad;// flat weighting:      const float w = 1.f;      W  += w;      x  += w*xo;      y  += w*yo;      Vx += w*vxo;     Vy += w*vyo;      xx += w*xo*xo;   yy += w*yo*yo;   xy += w*xo*yo;      xVx += w*xo*vxo; xVy += w*xo*vyo;      yVx += w*yo*vxo; yVy += w*yo*vyo;    }// flat weighting:   W = 1.f*n;    xx  = xx*W - x*x;   xy  = xy*W - x*y;   yy = yy*W - y*y;    xVx = xVx*W - x*Vx; xVy = xVy*W - x*Vy;    yVx = yVx*W - y*Vx; yVy = yVy*W - y*Vy;    float Det = xx*yy - xy*xy;    if (fabs(Det)<1.e-3f) { // data aligned?!?      // printf( "{xx}:%.6f  {yy}:%.6f  {xy}:%6f\n", xx, yy, xy );      if (fabs(xy)<1.e-3f) {          // => either xx or yy is 0.        if (fabs(xx)>=1.e-3f) {          Det = Scale / xx;          a = xVx * Scale;          b = 0.;          c = xVy * Scale;          d = 0.;        }        else if (fabs(yy)>=1.e-6f) {          Det = Scale / yy;          a = 0.;          b = yVx * Scale;          c = 0.;          d = yVy * Scale;        }        else { a = b = c = d = 0.; }      }      else {      // {xy}.{xy} = {xx}.{yy}. Data are aligned.        a = b = c = d = 0.;      }    }    else {      Det = Scale / Det;      a = ( xVx*yy - yVx*xy ) * Det;      b = ( yVx*xx - xVx*xy ) * Det;      c = ( xVy*yy - yVy*xy ) * Det;      d = ( yVy*xx - xVy*xy ) * Det;    }    W = 1.f / W;    vx0 = ( Scale*Vx - a*x - b*y ) * W;    vy0 = ( Scale*Vy - c*x - d*y ) * W;#if 0    vx0 = 0.5f*GMC_RND(2.f*vx0);    vy0 = 0.5f*GMC_RND(2.f*vy0);    a = (0.5f/Frame->Width )*GMC_RND( a*2.f*Frame->Width  );    c = (0.5f/Frame->Width )*GMC_RND( c*2.f*Frame->Width  );    b = (0.5f/Frame->Height)*GMC_RND( b*2.f*Frame->Height );    d = (0.5f/Frame->Height)*GMC_RND( d*2.f*Frame->Height );#endif//    printf( "Nb Smpl:%d/%d  Params:vx0=%.3f vy0=%.3f a=%.3f b=%.3f c=%.3f d=%.3f W=%3f\n", Nb_Smpl, MB_W*MB_H, vx0, vy0, a,b, c,d, W );    float dVx = 0., dVy = 0.;    for(n=0; n<Nb_Smpl; ++n) {      i = Smpl[n][0]; j = Smpl[n][1];      const float x = 16.f*i;      const float y = 16.f*j;      Vx = vx0 + a*x + b*y;      Vy = vy0 + c*x + d*y;//      printf( "%3f/%3f %3f/%3f\n", Vx, Scale*MVs[2*i + j*MV_Up][0], Vy, Scale*MVs[2*i + j*MV_Up][1] );      Vx -= Scale*MVs[2*i + j*MV_Up][0];      Vy -= Scale*MVs[2*i + j*MV_Up][1];       dVx += ABS(Vx);      dVy += ABS(Vy);    }    dVx /= Nb_Smpl; dVy /= Nb_Smpl;    if (dVx<0.3f) dVx = 0.3f;    if (dVy<0.3f) dVy = 0.3f;    int Nb0 = Nb_Smpl;    n = 0;    while(n<Nb_Smpl)    {      i = Smpl[n][0]; j = Smpl[n][1];      const float x = 16.f*i;      const float y = 16.f*j;      Vx = vx0 + a*x + b*y - Scale*MVs[2*i + j*MV_Up][0];      Vy = vy0 + c*x + d*y - Scale*MVs[2*i + j*MV_Up][1];      if (ABS(Vx)>dVx || ABS(Vy)>dVy) {        --Nb_Smpl;        Smpl[n][0] = Smpl[Nb_Smpl][0];        Smpl[n][1] = Smpl[Nb_Smpl][1];      }      else n++;    }      //    printf( "=> Nb_Smpl:%d/%d   Box: dVx=%f, dVy=%f\n", Nb_Smpl, Nb0, dVx, dVy );    if (Nb_Smpl<8 || Nb_Smpl==Nb0)      break;  }  if ( (Nb_Smpl<8) && ((GMC_Mode&2)==0) )    return;  // Status quo not reached    // ok, we seem to have some global motion params available.    // Time to clean things up.  GMC_Warps[0][0] = GMC_RND( vx0 );              SKL_ASSERT(GMC_Warps[0][0]>=-32768 && GMC_Warps[0][0]<=32767);  GMC_Warps[0][1] = GMC_RND( vy0 );              SKL_ASSERT(GMC_Warps[0][0]>=-32768 && GMC_Warps[0][0]<=32767);  GMC_Warps[1][0] = GMC_RND( a*Frame->Width  );  SKL_ASSERT(GMC_Warps[1][0]>=-32768 && GMC_Warps[1][0]<=32767);  GMC_Warps[1][1] = GMC_RND( c*Frame->Width  );  SKL_ASSERT(GMC_Warps[1][1]>=-32768 && GMC_Warps[1][1]<=32767);  GMC_Warps[2][0] = GMC_RND( b*Frame->Height );  SKL_ASSERT(GMC_Warps[2][0]>=-32768 && GMC_Warps[2][0]<=32767);  GMC_Warps[2][1] = GMC_RND( d*Frame->Height );  SKL_ASSERT(GMC_Warps[2][1]>=-32768 && GMC_Warps[2][1]<=32767);//  printf( " => (%d,%d) (%d,%d) (%d,%d)\n", GMC_Warps[0][0], GMC_Warps[0

⌨️ 快捷键说明

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