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

📄 skl_mpg4_enc.cpp

📁 mpeg4编解码器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    }  }  if (Field_DCT>=0)   // interlace?  {    if (Cbp!=0) Bits->Put_Bits( Field_DCT, 1 );    if (B_Type!=SKL_MB_DIRECT)    {      Bits->Put_Bits( Field_Pred, 1 );      if (Field_Pred) {        if (B_Type!=SKL_MB_BWD)          Bits->Put_Bits( Field_Dir&3, 2 ); // Fwd Top/Bottom field select.        if (B_Type!=SKL_MB_FWD)          Bits->Put_Bits( Field_Dir>>2, 2 ); // Bwd Top/Bottom field select.      }    }  }  const SKL_SAFE_INT Pos = Bits->Write_Bit_Pos();    if (B_Type == SKL_MB_DIRECT) {    if (!ModB1)      Write_Vector(Bits, dMVs[0], 1);   // FCode=1, always  }  else {    if (B_Type!=SKL_MB_BWD) {      Write_Vector(Bits, dMVs[0], Fwd_Code);      if (Field_Pred)        Write_Vector(Bits, dMVs[1], Fwd_Code);    }    if (B_Type!=SKL_MB_FWD) {      Write_Vector(Bits, dMVs[2], Bwd_Code);      if (Field_Pred)        Write_Vector(Bits, dMVs[3], Bwd_Code);    }  }  MV_Bits += Bits->Write_Bit_Pos() - Pos;  const SKL_SAFE_INT Pos2 = Bits->Write_Bit_Pos();    SKL_INT16 *C = In;  for(int blk=0; blk<6; ++blk) {    if (Last[blk]>=0)      Write_Coeffs( Bits, C, SKL_MP4_I::Scan_Order[0], Last[blk], B16_17_Tabs[0]);    C += 64;  }  Texture_Bits += Bits->Write_Bit_Pos() - Pos2;  Set_Not_Intra();}//////////////////////////////////////////////////////////// encoder-only MB ops//////////////////////////////////////////////////////////void SKL_MB_ENC::Copy_8To16(SKL_INT16 Out[6*64]) const{  VOL->MB_Ops.Copy_16x8_8To16(Out+0*64, Y1,   YBpS);  VOL->MB_Ops.Copy_16x8_8To16(Out+2*64, Y2,   YBpS);  VOL->MB_Ops.Copy_8x8_8To16( Out+4*64, U,    BpS);  VOL->MB_Ops.Copy_8x8_8To16( Out+5*64, V,    BpS);}void SKL_MB_ENC::Diff_8To16(SKL_INT16 Out[6*64]) const{  VOL->MB_Ops.Diff_16x8_8To16(Out+0*64, Y1,   YBpS);  VOL->MB_Ops.Diff_16x8_8To16(Out+2*64, Y2,   YBpS);  VOL->MB_Ops.Diff_8x8_8To16( Out+4*64, U,    BpS);  VOL->MB_Ops.Diff_8x8_8To16( Out+5*64, V,    BpS);}//////////////////////////////////////////////////////////// DC/AC prediction//////////////////////////////////////////////////////////int SKL_MB_ENC::Select_DC_AC_Pred(SKL_INT16 In[6*64],                                  int Pred_Dirs[6]){  int i, blk;  int Preds[6][7+1];  // 7 predictors/blk + 1 'worthiness' flag  SKL_INT16 *C;  int S_With_AC = 0;  int S_Without_AC = 0;  for(C=In, blk=0; blk<6; ++blk)  {    int Pred_DC;    SKL_INT16 * const Left_AC = Lefts[blk];    const SKL_MB_DATA * const Top = Tops[blk];    SKL_MB_DATA * const Cur = Curs[blk];    const int AC_Q = Quant;    const int DC_Q = SKL_MP4_I::DC_Scales[(blk<4)][AC_Q-1];    Preds[blk][7] = 1;          // a priori guess: it's worth predicting      // first, deal with DC    const SKL_INT16 a = Cur[-1].DC;    const SKL_INT16 b = Top[-1].DC;    const SKL_INT16 c = Top[ 0].DC;    if (ABS(a-b)<ABS(c-b)) {    // vertical      Pred_DC = c;      if (Top[0].Q<=0)          // Potential prediction block is not intra.         Preds[blk][7] = 0;      // => Not worth AC predicting (dflt coeffs={0}).      Pred_Dirs[blk] = 1;    }    else {                      // horizontal      Pred_DC = a;      if (Cur[-1].Q<=0)         // Potential prediction block is not intra.         Preds[blk][7] = 0;      // => Not worth AC predicting (dflt coeffs={0}).      Pred_Dirs[blk] = 2;    }      // predict DC no matter what    Cur->DC = C[0] * DC_Q;      // TODO: redundant with Dequant_XXX (except saturation?)    Cur->Q = AC_Q;              // this will mark the block as 'Intra'    SKL_ASSERT(C[0]>=0 && Pred_DC>=0);    if (Pred_DC>0)      C[0] -= ( Pred_DC + (DC_Q>>1) ) / DC_Q;    if (!Preds[blk][7])         // done?      goto End;      // guess whether AC prediction is worth it or not    if (Pred_Dirs[blk]==1) {    // vertical      for(i=0; i<7; ++i) {        Preds[blk][i] = C[i+1];        if (Top->AC[i]!=0) {          S_Without_AC += ABS(C[i+1]);          if (Top[0].Q!=AC_Q) {            int Corr = Top->AC[i]*Top[0].Q;            Preds[blk][i] -= DIV_ROUND(Corr, AC_Q);          }          else Preds[blk][i] -= Top->AC[i];          S_With_AC += ABS(Preds[blk][i]);        }        // else: if AC[i]==0, both predicted and        // unpredicted coeffs will weight the same        // in sums, and cancel each others.         // So we don't add either of them.      }    }    else {                      // horizontal      for(i=0; i<7; ++i) {        Preds[blk][i] = C[8*(i+1)];        if (Left_AC[i]!=0) {          S_Without_AC += ABS(C[8*(i+1)]);          if (Cur[-1].Q!=AC_Q) {            int Corr = Left_AC[i]*Cur[-1].Q;            Preds[blk][i] -= DIV_ROUND(Corr, AC_Q);          }          else Preds[blk][i] -= Left_AC[i];          S_With_AC += ABS(Preds[blk][i]);        }      }    }End:      // store for other predictions    for(i=0; i<7; ++i) {      Cur->AC[i] = C[i+1];      Left_AC[i] = C[8*(i+1)];    }    C += 64;  }  if (S_Without_AC>S_With_AC)   // Ok. Go for it!  {    for(C=In, blk=0; blk<6; ++blk) {      if (Preds[blk][7]) {        if (Pred_Dirs[blk]==1)           for(i=0; i<7; ++i) C[i+1] = Preds[blk][i];        else          for(i=0; i<7; ++i) C[8*(i+1)] = Preds[blk][i];      }      C += 64;    }    return 1;  }  else return 0;                // was no avail...}//////////////////////////////////////////////////////////////    Compressive part//// Let's explain a little bit what's going on. We're here// to perform the following steps:////   1) Import YUV 8b-data from picture to 16b DCT-coeffs C[]//   2) FDCT( C[] )//   3) C[] /= Q        (quantization)//   4) C[] -= Preds[]  (remove prediction, if any)//   5) Encode C[]      (into bitstream)//   6) Decode C[]//   7) C[] += Preds//   8) C[] *= Q        (dequantization)//   9) IDCT( C[] )     (backward transform)//  10) Export reconstructed data to picture////  Notes:// . Using FDCT and scale-based quantization is not mandatory// in itself. Only does the MPEG familly of hybrid encoder// requires it. But you can instead try wavelets, cosmic rays-based// quantization, whatever. :) The encoder (almost) doesn't care.//// . Also, the actual way spatio(-temporal) predictors are chosen// pertain to the encoding format (here: MPEG4) only.// The frame analyzer/motion estimator shouldn't care (much)// about it. MPEG2 used to use different predictors, for instance.//// . Steps 6->10 are reserved to the decoder, but we// have, as an encoder, to keep sync with what will// be perceived by the decoder. ////// Anyway, the *only* lossy step is 3). Afterward, C[] // remain constant until step 8). Hence, we need not perform// steps 6-7: just save C[] after quantization, and restore it // for step 8).////   Now, we can reorder the job as://// a) Import(C) | FDCT(C) | C/=Q | Copy C in C' | C'*=Q / IDCT(C') | Export(C')// b) C -= Preds | Encode(C)////  Step a) is function 'Decimate_Intra()', whereas step b) is 'Encode_Intra()'//// There are additional subtleties possible during the//  FDCT| C/=Q | C*=Q | IDCT stage. In particular, one can save some// transposes, at the expense of playing with zigzag orders, predicted// directions, etc. One can also try to combine the C/=Q and C*=Q steps// in a efficient manner, mix with DCTs, etc... Research is open.//// Finally, note that Inter coding is almost the same. Only does it requires// some kind of motion estimation to Import() efficiently. But you can// try random Motion Vectors too, no pb.//// That's it. Now, go!////////////////////////////////////////////////////////////void SKL_MB_ENC::Decimate_Intra(SKL_INT16 Out[12*64]) const{  Copy_8To16(Out+6*64);         // import  SKL_INT16 *C = Out;           // Decimate  const SKL_MP4_ENC_I * const Vol = (const SKL_MP4_ENC_I *)VOL;  for(int blk=0; blk<6; ++blk) {    const int DC_Q = SKL_MP4_I::DC_Scales[(blk<4)][Quant-1];    Vol->Decimate_Intra(C, C+6*64, Quant, DC_Q);    C += 64;  }  Copy_16To8(Out+6*64);         // transfer back decimated data}void SKL_MB_ENC::Decimate_Inter(SKL_INT16 Out[12*64]){  SKL_ASSERT(MC_Sel==0);  if (MB_Type==SKL_MB_SKIPPED) {    Predict_With_0MV(VOL->Copy_Ops, 1);    Store_Zero_MV();    return;  }    // Fwd predict  int Skippable = (dQuant==0) && SKL_IS_ZERO_MV(MVs[0]) && (VOL->Coding!=S_VOP);  Copy_8To16(Out + 6*64);              // save original data  if (Field_Pred) {                    // form predictions    Predict_Fields(MVs, VOL->Copy_Ops, 1, Field_Dir);    Store_16x8_MV(&MVs2[0], &MVs[0]);    SKL_COPY_MV(MVs[1], MVs2[0]);      // update left predictor    if (Skippable) Skippable &= SKL_IS_ZERO_MV(MVs2[0]);  }  else {    if (MB_Type!=SKL_MB_INTER4V) {      Predict_With_1MV(MVs[0], VOL->Copy_Ops, 1);      Store_16x16_MV();    }    else {      Predict_With_4MV(&MVs[0], &MVs2[0], VOL->Copy_Ops, 1);      if (Skippable) {        Skippable &= SKL_IS_ZERO_MV(MVs [1]);        Skippable &= SKL_IS_ZERO_MV(MVs2[0]);        Skippable &= SKL_IS_ZERO_MV(MVs2[1]);      }    }  }  Diff_8To16(Out + 6*64);              // diff original/predicted data  SKL_INT16 *C = Out;                  // Decimate and set Cbp  Cbp = 0x00;  const SKL_MP4_ENC_I * const Vol = (const SKL_MP4_ENC_I*)VOL;  for(int blk=0; blk<6; ++blk)  {    const int SAV = Vol->Decimate_Inter(C, C+6*64, Quant);    if (SAV>0) {      Last[blk] = Find_Last(C, SKL_MP4_I::Scan_Order[0], 63);      SKL_ASSERT(Last[blk]>=0);      Cbp |= 1<<(5-blk);    }    else Last[blk] = -1;    C += 64;  }  if (!Skippable || Cbp!=0)    Add_16To8(Out + 6*64);             // transfer back decimated delta data    else    MB_Type = SKL_MB_SKIPPED;          // won't be coded (don't transfer back data)}void SKL_MB_ENC::Decimate_Inter_GMC(SKL_INT16 Out[12*64]){  SKL_ASSERT(Field_Pred==0 && MC_Sel!=0);  SKL_ASSERT(MB_Type==SKL_MB_INTER || MB_Type==SKL_MB_SKIPPED);  if (MB_Type!=SKL_MB_SKIPPED) Copy_8To16(Out+6*64); // save original data  Predict_GMC();  if (MB_Type!=SKL_MB_SKIPPED) Diff_8To16(Out+6*64); // diff original/predicted data  else return;                                       // Done  SKL_INT16 *C = Out;                                // Decimate and set Cbp  Cbp = 0x00;  const SKL_MP4_ENC_I * const Vol = (const SKL_MP4_ENC_I *)VOL;  for(int blk=0; blk<6; ++blk)  {    const int SAV = Vol->Decimate_Inter(C, C+6*64, Quant);    if (SAV>0) {      Last[blk] = Find_Last(C, SKL_MP4_I::Scan_Order[0], 63);      SKL_ASSERT(Last[blk]>=0);      Cbp |= 1<<(5-blk);    }    else Last[blk] = -1;    C += 64;  }  const int Skippable = (dQuant==0);  if (!Skippable || Cbp!=0) Add_16To8(Out+6*64);     // transfer back decimated delta data  else MB_Type = SKL_MB_SKIPPED;                     // won't be coded (don't transfer back data)}//////////////////////////////////////////////////////////// bitstream coding//////////////////////////////////////////////////////////static void Stuffed_Align(SKL_FBB * const Bits)    // hardcoded Table 6.2{  int Left = 8 - (Bits->Bits_Left & 7);  Bits->Put_Bits( SKL_BMASKS::And[Left-1], Left );  Bits->Flush_Write();}static void Write_User_Data(SKL_FBB * const Bits, int Len, const SKL_BYTE *Data){  Bits->Flush_Write();  Bits->Put_DWord( USER_DATA_CODE );    // TODO: check data doesn't emulate a start code?  while(Len-->0) Bits->Put_Bits( *Data++, 8 );  Stuffed_Align(Bits);}static void Write_Matrix(SKL_FBB * const Bits, const SKL_BYTE *M){  int Last = M[SKL_MP4_I::Scan_Order[0][63]];  int i, j;  for(j=62; j>0; --j) if (M[SKL_MP4_I::Scan_Order[0][j]]!=Last) break;  for(i=0; i<=j; ++i) Bits->Put_Bits( M[SKL_MP4_I::Scan_Order[0][i]], 8 );  if (j<63)    Bits->Put_Bits(0, 8);}static void Write_Sprite_Comp(SKL_FBB * const Bits, int v){  if (v) {    int Size;    const int Sign = (v<0);    if (Sign) {       Size = SKL_BMASKS::Log2(-v);      v += SKL_BMASKS::And[Size];    }    else {      Size = SKL_BMASKS::Log2(v);      v |= SKL_BMASKS::Or[Size];    }    SKL_ASSERT(Size>=0 && Size<15);    Bits->Put_Bits(Spr_Tab_B33[Size].Val,Spr_Tab_B33[Size].Len);    Bits->Put_Bits(v, Size);  }  else Bits->Put_Bits(Spr_Tab_B33[0].Val,Spr_Tab_B33[0].Len);}static void Write_Sprite_Trajectory(SKL_FBB * const Bits, const int Pts[][2], int Nb){  for(int n=0; n<Nb; ++n) {    Write_Sprite_Comp(Bits, Pts[n][0]);    Bits->Put_Bits(1,1);    // marker bit    Write_Sprite_Comp(Bits, Pts[n][1]);    Bits->Put_Bits(1,1);    // marker bit  }}  // section 6.2.3void SKL_MP4_ENC_I::Write_VOL_Header(SKL_FBB * const Bits) const{  int Verid = (Quarter>0 || Reduced_VOP>=0 || Sprite_Mode>=SPRITE_GMC) ? 2 : 1;

⌨️ 快捷键说明

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