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

📄 skl_mpg4_anl.cpp

📁 mpeg4编解码器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}static inline void Median(SKL_MV Dst, const SKL_MV A, const SKL_MV B, const SKL_MV C){  Dst[0] = Median(A[0],B[0],C[0]);  Dst[1] = Median(A[1],B[1],C[1]);}static inline void Median2(SKL_MV Dst, const SKL_MV A, const SKL_MV B){  Dst[0] = Median(A[0],B[0],0);  Dst[1] = Median(A[1],B[1],0);}inline void ME_MAP::Set_MV_Predictor(const SKL_MV * const Src,                                      const int MV_Stride, const int Blk,                                     const int ABits){  SKL_ASSERT(Blk>=0 && Blk<4);  const SKL_MV * const MV_L  = Src - 1;  const SKL_MV * const MV_T  = Src - MV_Stride;  const SKL_MV * const MV_TR = MV_T + Top_Neighbors[Blk];  const int Pred_Type = Pred_Type_ABits[ABits][Blk];  switch(Pred_Type) {    default:    case 0:      Median(Pred, MV_L[0], MV_T[0], MV_TR[0]);    break;    case 1:      SKL_COPY_MV(Pred, *MV_L);    break;    case 2:      Median2(Pred, MV_T[0], MV_TR[0]);    break;    case 3:      Median2(Pred, MV_L[0], MV_TR[0]);    break;    case 4:      Median2(Pred, MV_L[0], MV_T[0]);    break;    case 5:      SKL_COPY_MV(Pred, *MV_T);    break;    case 6:      SKL_COPY_MV(Pred, *MV_TR );    break;    case 7:      SKL_ZERO_MV(Pred);    break;  }  if (Sub_Prec_Shift==2) {    IPred[0] = Pred[0]/4;    IPred[1] = Pred[1]/4;    // IPred[0] = (Pred[0]+2)>>2;    // IPred[1] = (Pred[1]+2)>>2;  }  else {    IPred[0] = Pred[0]/2;    IPred[1] = Pred[1]/2;    // IPred[0] = (Pred[0]+1)>>1;    // IPred[1] = (Pred[1]+1)>>1;  }}inline void ME_MAP::Set_FP_MV_Predictor(SKL_MV Pred, const SKL_MP4_MAP * const Map,                                        const int Map_Stride, const int ABits){  const SKL_MV * const MV_L  = &Map[-1].MV;  const SKL_MV * const MV_T  = &Map[-Map_Stride].MV;  const SKL_MV * const MV_TR = &Map[-Map_Stride+1].MV;  const int Pred_Type = Pred_Type_ABits[ABits][0];  switch(Pred_Type) {    default:    case 0:      Median(Pred, MV_L[0], MV_T[0], MV_TR[0]);    break;    case 1:      SKL_COPY_MV(Pred, *MV_L);    break;    case 2:      Median2(Pred, MV_T[0], MV_TR[0]);    break;    case 3:      Median2(Pred, MV_L[0], MV_TR[0]);    break;    case 4:      Median2(Pred, MV_L[0], MV_T[0]);    break;    case 5:      SKL_COPY_MV(Pred, *MV_T);    break;    case 6:      SKL_COPY_MV(Pred, *MV_TR );    break;    case 7:      SKL_ZERO_MV(Pred);    break;  }}//////////////////////////////////////////////////////////// global pass//////////////////////////////////////////////////////////static inline void Update_Map_Data(SKL_MP4_MAP *const Map,                                   SKL_MP4_MAP *const pMap,                                   SKL_UINT32 Sad16, const SKL_MV MV){  Map->Sad16 = Sad16;  SKL_COPY_MV(Map->MV, MV);  if (pMap) {    Map->Acc[0] = 2*Map->MV[0] - pMap->MV[0];    Map->Acc[1] = 2*Map->MV[1] - pMap->MV[1];  }  else {    SKL_ZERO_MV(Map->Acc);  }}  // Populates MVs[], Map->Type and Map->Flagsvoid SKL_MP4_ANALYZER_I::Global_Pass(SKL_MP4_INFOS * const Frame){  const int FCode = RND(MV_Search_Window);  int Nb_Intras   = 0;  int Nb_Relevant = 0;  Reset_Stats();  // will store previous Last_Avrg_MV (if any)  ME_MAP Cursor(Frame);  SKL_UINT32 SAD_Hi   = SAD_Hi_Limit;  SKL_UINT32 SAD_Lo   = SAD_Low_Limit;    // for now, disable 4v search with reduced VOP  const int Search_4V = (Reduced_Frame<1) && (Inter4V_Probing>0);  const int BpS = Frame->BpS;  SKL_UINT32 Sad4_Penalty;  // penalty for 4v  SKL_UINT32 Sad2_Penalty;  // penalty for field interlacing  METRIC Metric_16x16, Metric_8x8, Metric_16x8;  METRIC_AVRG Metric_16x16_Avrg, Metric_8x8_Avrg, Metric_16x8_Avrg;  METRIC_DEV Metric_Dev;  switch( Search_Metric ) {    case 2:      Metric_16x16 = Frame->Img_Dsp->Hadamard_SAD_16x16;      Metric_16x8  = Frame->Img_Dsp->Hadamard_SAD_16x8_Field;      Metric_8x8   = Frame->Img_Dsp->Hadamard_SAD_8x8;      Metric_Dev   = Frame->Img_Dsp->Hadamard_Dev_16x16;      Metric_16x16_Avrg  = Frame->Img_Dsp->SAD_Avrg_16x16;      Metric_16x8_Avrg   = Frame->Img_Dsp->SAD_Avrg_16x8;      Metric_8x8_Avrg    = Frame->Img_Dsp->SAD_Avrg_8x8;      Cursor.Lambda = (int)( Q_Cur*0.9f*Lambda );      SAD_Lo = 2*SAD_Lo;      SAD_Hi = 2*SAD_Hi;      Sad4_Penalty = (SKL_UINT32)( .2f * Q_Cur*Lambda );      Sad2_Penalty = (SKL_UINT32)( .6f * Q_Cur*Lambda );    break;    case 1:      Metric_16x16 = Frame->Img_Dsp->SSD_16x16;      Metric_16x8  = Frame->Img_Dsp->SSD_16x8_Field;      Metric_8x8   = Frame->Img_Dsp->SSD_8x8;      Metric_Dev   = Frame->Img_Dsp->Sqr_Dev_16x16;      Metric_16x16_Avrg  = Frame->Img_Dsp->SAD_Avrg_16x16;      Metric_16x8_Avrg   = Frame->Img_Dsp->SAD_Avrg_16x8;      Metric_8x8_Avrg    = Frame->Img_Dsp->SAD_Avrg_8x8;      Cursor.Lambda = (int)( Q_Cur*Q_Cur*3.5f*Lambda );      SAD_Lo = SAD_Lo;      SAD_Hi = SAD_Hi;      Sad4_Penalty = (SKL_UINT32)( 0.1f * Q_Cur * Q_Cur*Lambda );      Sad2_Penalty = (SKL_UINT32)( 3.8f * Q_Cur * Q_Cur*Lambda );    break;    default:      Metric_16x16 = Frame->Img_Dsp->SAD_16x16;      Metric_16x8  = Frame->Img_Dsp->SAD_16x8_Field;      Metric_8x8   = Frame->Img_Dsp->SAD_8x8;      Metric_Dev   = Frame->Img_Dsp->Abs_Dev_16x16;      Metric_16x16_Avrg  = Frame->Img_Dsp->SAD_Avrg_16x16;      Metric_16x8_Avrg   = Frame->Img_Dsp->SAD_Avrg_16x8;      Metric_8x8_Avrg    = Frame->Img_Dsp->SAD_Avrg_8x8;      Cursor.Lambda = (int)( Q_Cur*0.8f*Lambda );      SAD_Lo = 2*SAD_Lo;      SAD_Hi = 2*SAD_Hi;      Sad4_Penalty = (SKL_UINT32)( 2.4f * Q_Cur*Lambda );      Sad2_Penalty = (SKL_UINT32)( 0.7f * Q_Cur*Lambda );    break;  }  const SKL_UINT32 SKIP_Limit = SAD_Lo >> 2;   // TODO: Fine tune. Is it a good idea, btw?  Cursor.Search_Method = MV_Searchs[Search_Method];  Cursor.Metric        = Metric_16x16;  Cursor.Metric_Avrg   = Metric_16x16_Avrg;  Cursor.Set_FCode( FCode, Subpixel_Precision );  const int MV_Stride = Frame->MV_Stride;  const int Map_Stride = Frame->MB_W;  SKL_MP4_MAP *Map  = Frame->Cur->Map;  SKL_MV *MVs       = Frame->Cur->MV;  SKL_MV *pMVs      = (Frame->Past ? Frame->Past->MV  : 0);  SKL_MP4_MAP *pMap = (Frame->Past ? Frame->Past->Map : 0);    // Note: Hi_Mem is only worth of QPel  const int Use_HPels = (Hi_Mem && Frame->Past!=0) && (Subpixel_Precision==2);  if (Use_HPels) Set_Half_Pels(Frame, Frame->Past);  else _HPels[0] = 0;   // sanity check  for(int y=0; y<Frame->Height; y+=16)  {    Cursor.New_Scanline(y);    for(int x=0; x<Frame->Width; x+=16)    {//      SKL_MV Maxs[2];      const int ABits = (x>0) | ((y>0)<<1) | ((x+16<Frame->Width)<<2) | ((y+16<Frame->Height)<<3);      Cursor.Set_MV_Predictor(&MVs[0], MV_Stride, 0, ABits);      SKL_UINT32 Dist0 = Cursor.Start(Metric_16x16, Metric_16x16_Avrg);      // Dist0 is distortion for mv=(0,0)      SKL_UINT32 Sad0 = Dist0 + Cursor.MV_Bits_Cost(0,0); // Cost for mv=(0,0)      Cursor.Cache_Sad(Cursor.xM<0 ? Cursor.xM : Cursor.xm>0 ? Cursor.xm : 0,                       Cursor.yM<0 ? Cursor.yM : Cursor.ym>0 ? Cursor.ym : 0,                       Sad0);      Nb_Relevant += (Dist0>300);      Map->Flags = 0; // a priori: no field-DCT      Map->dQ    = 0;      Map->Sad   = Sad0;      Map->Sad16 = Sad0;      Map->Type  = SKL_MAP_16x16;  // default mode: INTER, with 1MV      SKL_ASSERT(Cursor.xo == x && Cursor.yo==y);      SKL_ASSERT(Cursor.Src == Frame->Cur->Y  + x + y*BpS);      SKL_ASSERT(Cursor.Ref == Frame->Past->Y + x + y*BpS);      SKL_UINT32 Sad_Limit;#if 1      if (Dist0<SKIP_Limit) {        SKL_UINT32 Chroma_SAD;        const int Chroma_Off = (x/2) + (y/2)*BpS;        Chroma_SAD  = Metric_8x8(Frame->Cur->U + Chroma_Off, Frame->Past->U + Chroma_Off, BpS);        Chroma_SAD += Metric_8x8(Frame->Cur->V + Chroma_Off, Frame->Past->V + Chroma_Off, BpS);        if (Chroma_SAD*2<SKIP_Limit) {          Map->Type = SKL_MAP_SKIPPED;          SKL_ZERO_MV(MVs[0]);  // <- prepare, in case it gets later promoted to INTER_16x16 (GMC)          Update_Map_Data(Map, pMap, Dist0, MVs[0]);          goto Done_16x16;        }      }//      if (Dist0<SAD_Lo*2) Cursor.Best_Sad = SAD_Lo*2;//      else if (Dist0>SAD_Hi*2) Cursor.Best_Sad = SAD_Hi*2;#endif      Cursor.Eval_If_Valid(Cursor.Pred);#if 1      if (ABits&7) {        SKL_MV Med;        Cursor.Set_FP_MV_Predictor(Med, Map, Map_Stride, ABits);        Cursor.Eval_FP_If_Valid(Med);      }#endif      if (Cursor.Best_Sad<256)        goto Skip_Search;      Sad_Limit = Map[0].Sad16;      if (pMap) {//        Cursor.Eval_FP_If_Valid(pMap[0].MV);  // past colocated        if (ABits&4)          Cursor.Eval_FP_If_Valid(pMap[1].MV);    // past left      }      if (ABits&1) {    // left        Cursor.Eval_FP_If_Valid(Map[-1].MV);        if (Map[-1].Sad16<Sad_Limit) Sad_Limit = Map[-1].Sad16;      }      if (ABits&2) {    // top        Cursor.Eval_FP_If_Valid(Map[-Map_Stride].MV);        if (Map[-Map_Stride].Sad16<Sad_Limit) Sad_Limit = Map[-Map_Stride].Sad16;        if (ABits&4) {  // top-right          Cursor.Eval_FP_If_Valid(Map[-Map_Stride+1].MV);          if (Map[-Map_Stride+1].Sad16<Sad_Limit) Sad_Limit = Map[-Map_Stride+1].Sad16;        }      }      if (Cursor.Best_Sad < Sad_Limit)        goto Skip_Search;             if (pMap && Cursor.Best_Sad>2*SAD_Lo)      {#if 1        if (ABits&1) Cursor.Eval_FP_If_Valid(pMap[-1].MV);    // past left        if (ABits&4) Cursor.Eval_FP_If_Valid(pMap[ 1].MV);    // past right        if (ABits&2) Cursor.Eval_FP_If_Valid(pMap[-Map_Stride].MV);    // past top        if (ABits&8) Cursor.Eval_FP_If_Valid(pMap[ Map_Stride].MV);    // past bottom        Cursor.Eval_FP_If_Valid(pMap[0].Acc);    // accelerator#endif        Cursor.Eval_If_Valid(Last_Avrg_MV);      // Last avrg MV        Cursor.Eval_FP_If_Valid(pMap[0].MV);     // past colocated        if ((ABits&12)==12) Cursor.Eval_FP_If_Valid(pMap[Map_Stride+1].MV);    // past bottom right        if (Cursor.Best_Sad < Sad_Limit)          goto Skip_Search;//        if (IS_EQUAL_MV(Cursor.Best_MV,pMap[0].MV) && Cursor.Best_Sad<pMap[0].Sad16)//          goto Skip_Search;      }      Cursor.Search();Skip_Search:      Update_Map_Data(Map, pMap, Cursor.Best_Sad, Cursor.Best_MV);      if (Cursor.Best_Sad > SAD_Hi &&           Cursor.Best_Sad > Metric_Dev(Cursor.Src, BpS))      {        Map->Type = SKL_MAP_INTRA;        Nb_Intras++;        SKL_ZERO_MV(MVs[0]);        goto Done_16x16;      }      if (Use_HPels) Cursor.Refine_MV_HPels(MVs[0], Subpixel_Precision, Rounding, _HPels);      else           Cursor.Refine_MV_16x16(MVs[0], Subpixel_Precision, Rounding);      Map->Sad = Cursor.Best_Sad;      if (Interlace_Field>0)      {        if (Field_Pred_Probing<100) {            // 50-60% is a good compromise between speed and probing          const SKL_UINT32 Sad_Sub_Limit = Cursor.Best_Sad * (100-Field_Pred_Probing) /100;          const SKL_BYTE * Rf = Cursor.Ref + Cursor.Best_MV[0] + Cursor.Best_MV[1]*BpS;          SKL_UINT32 Sad2_0;          Sad2_0  = Metric_16x8(Cursor.Src     , Rf, BpS);          if (Sad2_0>=Sad_Sub_Limit) goto Go_Field_Pred;          Sad2_0 = Metric_16x8(Cursor.Src + BpS, Rf, BpS);          if (Sad2_0>=Sad_Sub_Limit) goto Go_Field_Pred;          goto Done_Field;        }Go_Field_Pred:        {          SKL_UINT32 Sad2, Sad16, Saved_Sad = Cursor.Best_Sad;          SKL_MV Saved_MV, Best_MV;          SKL_COPY_MV( MVs[1], MVs[0] );          SKL_COPY_MV( Saved_MV, MVs[0] );          SKL_COPY_MV( Best_MV, Cursor.Best_MV );             Cursor.Metric = Metric_16x8;          Cursor.Metric_Avrg   = Metric_16x8_Avrg;          Sad16 = Cursor.Sub_Search(Map[0].MV, 0,0);          Sad2  = Cursor.Refine_MV_16x8(MVs[0], Subpixel_Precision, Rounding);          Sad16 += Cursor.Sub_Search(Map[0].MV, 0,1);          Sad2  += Cursor.Refine_MV_16x8(MVs[1], Subpixel_Precision, Rounding);            // penalty for going field-pred is very high (we'll pay 2mv+1bit per mb)          Sad2 = Sad2*12/10 + Sad2_Penalty;          Cursor.Set_Sub_Offset(0,0);          if (Sad2<Saved_Sad || Interlace_Field==2)          {            Map->Type = SKL_MAP_16x8; // -> use Field_Pred            Map->Sad   = Sad2;            MVs[1][1] += 1;   // compensate Src bottom field offset            MVs[MV_Stride+0][0] = (MVs[0][0]+MVs[1][0])>>1;            MVs[MV_Stride+0][1] = (MVs[0][1]+MVs[1][1])>>1;            SKL_COPY_MV(MVs[MV_Stride+1], MVs[MV_Stride+0]);            Update_Map_Data(Map, pMap, Sad16, MVs[MV_Stride+0]);                        Add_To_Stats(MVs[0]);            Add_To_Stats(MVs[1]);            goto Done;          }          else {            SKL_COPY_MV( MVs[0], Saved_MV );  // wasn't worth...            SKL_COPY_MV( Cursor.Best_MV, Best_MV );            Cursor.Best_Sad = Saved_Sad;            Cursor.Metric      = Metric_16x16;            Cursor.Metric_Avrg = Metric_16x16_Avrg;          }        }      }Done_Field:        // at this point, MVs[0] is in half/quarter pel unit...      SKL_ASSERT(Cursor.Is_In_Range(MVs[0]));      SKL_ASSERT(Map->Type==SKL_MAP_16x16);//      Set_Max(Maxs[0], MVs[0], Cursor.Pred);      if (Search_4V)      {#if 1        if (Inter4V_Probing<100)        {          const SKL_UINT32 Sad_Sub_Limit = Cursor.Best_Sad * (100-Inter4V_Probing) / 100;          const SKL_BYTE * Rf = Cursor.Ref + Cursor.Best_MV[0] + Cursor.Best_MV[1]*BpS;          SKL_UINT32 Sad4_0;          Sad4_0  = Metric_8x8(Cursor.Src           , Rf,   BpS);          if (Sad4_0>=Sad_Sub_Limit) goto Go_4v;          Sad4_0 = Metric_8x8(Cursor.Src + 8        , Rf+8, BpS);          if (Sad4_0>=Sad_Sub_Limit) goto Go_4v;          Rf += 8*BpS;

⌨️ 快捷键说明

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