📄 skl_mpg4_dec.cpp
字号:
int Level = VLC->Level; int Last = (Level<0); if (Run>=0) { if (Last) Level = -Level; Code = Bits->Get_Bits(VLC->Len+1); if (Code&1) Level = -Level; } else // Escape. Note: can only occur in Intra_B16_2[] { Bits->Discard(VLC->Len); if (Run==-3) // 3rd escape { Code = Bits->Get_Bits(1+6+1+12+1); Last = (Code>>20); Run = (Code>>14) & 0x3f; Level = (Code>> 1) & 0xfff; if (Level&0x800) Level |= (-1)^0xfff; } else { // 1rst and 2nd escape const int Esc2 = (Run==-2); Bits->Check_Bits(12); Code = Bits->Bits; SKL_ASSERT(Code>=0x00800000); if (Code>=0x30000000) VLC = Intra_B16_0 - 12 + (Code>>(20+6)); else if (Code>=0x13000000) VLC = Intra_B16_1 - 19 + (Code>>(20+4)); else if (Code>=0x06000000) VLC = Intra_B16_2 - 48 + (Code>>(20+1)); else /*if (Code>=0x00800000)*/ VLC = Intra_B16_3 - 8 + (Code>>(20+0)); // else break; /* error */ SKL_ASSERT(VLC->Run>=0); // Hope it's not an ESCAPE code again! ;) Code = Bits->Get_Bits(VLC->Len+1); Level = VLC->Level; Last = (VLC->Level<0); if (Last) Level = -Level; Run = VLC->Run; if (Esc2) Run += Max_RUN[0][Last][Level-1]; // 2nd escape else Level += Max_LEVEL[0][Last][Run]; // 1rst escape if (Code&1) Level = -Level; } } i += Run; if (i<64) { const int j = Zigzag[i++]; Coeff[j] = (SKL_INT16)Level; if (Last) break; } else break; /* error */ }}static int Read_Inter_AC(SKL_FBB *Bits, SKL_INT16 *Coeff, const int * const Zigzag){ int i = 0; int Rows = 0x00; while(1) { const SKL_DCT_VLC *VLC; Bits->Check_Bits_Word(12); SKL_UINT32 Code = Bits->Bits; SKL_ASSERT(Code>=0x00800000); if (Code>=0x30000000) VLC = Inter_B17_0 - 12 + (Code>>(20+6)); else if (Code>=0x13000000) VLC = Inter_B17_1 - 19 + (Code>>(20+4)); else if (Code>=0x06000000) VLC = Inter_B17_2 - 24 + (Code>>(20+2)); else if (Code>=0x00800000) VLC = Inter_B17_3 - 8 + (Code>>(20+0)); else break; /* error */ int Run = VLC->Run; int Level = VLC->Level; int Last = (Level<0); if (Run>=0) { if (Last) Level = -Level; if (Bits->Get_Bits(VLC->Len+1) & 1) Level = -Level; } else // Escape. Note: can only occur in Inter_B17_2[] { Bits->Discard_Safe(VLC->Len); if (Run==-3) // 3rd escape { SKL_UINT32 Pack = Bits->Get_Bits(1+6+1+12+1); Last = (Pack>>20); Run = (Pack>>14) & 0x3f; Level = ((SKL_INT32)Pack<<19)>>20; // Level = (Pack>> 1) & 0xfff; // if (Level&0x800) Level |= (-1)^0xfff; } else // 1rst and 2nd escape { const int Esc2 = (Run==-2); Bits->Check_Bits_Word(12); Code = Bits->Bits; SKL_ASSERT(Code>=0x00800000); if (Code>=0x30000000) VLC = Inter_B17_0 - 12 + (Code>>(20+6)); else if (Code>=0x13000000) VLC = Inter_B17_1 - 19 + (Code>>(20+4)); else if (Code>=0x06000000) VLC = Inter_B17_2 - 24 + (Code>>(20+2)); else if (Code>=0x00800000) VLC = Inter_B17_3 - 8 + (Code>>(20+0)); else break; /* error */ SKL_ASSERT(VLC->Run>=0); // Hope it's not an ESCAPE code again! ;) Run = VLC->Run; Level = VLC->Level; Last = (VLC->Level<0); if (Last) Level = -Level; if (Esc2) Run += Max_RUN[1][Last][Level-1]; // 2nd escape else Level += Max_LEVEL[1][Last][Run]; // 1rst escape if (Bits->Get_Bits(VLC->Len+1) & 1) Level = -Level; } } i += Run; if (i<64) { const int j = Zigzag[i++]; Coeff[j] = (SKL_INT16)Level; Rows |= SKL_MP4_I::Row_From_Index[j]; if (Last) break; } else break; /* error */ } return Rows;}//////////////////////////////////////////////////////////// Macroblock Cursor// TODO: this could be incrementalized (with 'Off')//////////////////////////////////////////////////////////SKL_MB::SKL_MB(const SKL_MP4_I * const Vol) : VOL(Vol) , BpS(Vol->BpS) , BpS8(8*Vol->BpS) , Fwd_CoLoc(Vol->Past->Y - Vol->Cur->Y) , Bwd_CoLoc(Vol->Future->Y - Vol->Cur->Y) , YTmp(Vol->Cur->Y - 16 - 16*Vol->BpS) // size: 17x16 , Map(Vol->Cur->Map){ // HACK! about YTmp: We form the qpel intermediate prediction in the // top left (margin) macroblock of the current edged picture. Since // the current picture is not supposed to be motion-searched for, we // can happily trash the edges. //(Note: I'm somewhat ashamed of such a hack :) Quant = VOL->Quant; Prev_Quant = Quant; Field_DCT = VOL->Interlace ? 0 : -1; MV_Stride = VOL->MV_Stride; y = 0; MC_Sel = 0; Field_Dir = VOL->Field_Dir; // Init scan DC/AC predictors int i; MB_W = VOL->MB_W; if (VOL->Reduced_VOP>0) MB_W >>= 1; for(i=0; i<2*MB_W; ++i) VOL->Y_Preds[0][i].Set_Not_Intra(); // reset Top Y for(i=0; i<MB_W; ++i) { VOL->C_Preds[0][ i].Set_Not_Intra(); // reset Top U VOL->C_Preds[0][VOL->MB_W+2+i].Set_Not_Intra(); // reset Top V } // invariants along each scan lines Lefts[0] = Left_ACs[0]; Lefts[1] = Left_ACs[0]; Lefts[2] = Left_ACs[1]; Lefts[3] = Left_ACs[1]; Lefts[4] = Left_ACs[2]; Lefts[5] = Left_ACs[3]; // compute resync marker len if (VOL->Resync) { int Len; if (VOL->Coding==I_VOP) Len = 16 + 1; else if (VOL->Coding==B_VOP) { Len = 16 + ((VOL->Bwd_Code > VOL->Fwd_Code) ? VOL->Bwd_Code : VOL->Fwd_Code); if (VOL->Quarter) Len += 1; } else /* P/S-VOP */ Len = 16 + VOL->Fwd_Code + (VOL->Quarter ? 1 : 0); Resync = Len; } else Resync = 0; Start_Scan();}SKL_MB::~SKL_MB() { // Store field parity for next frame ((SKL_MP4_I*)VOL)->Field_Dir = Field_Dir;}void SKL_MB::Set_Not_Intra(){ Curs[0]->Set_Not_Intra(); Curs[1]->Set_Not_Intra(); Curs[2]->Set_Not_Intra(); Curs[3]->Set_Not_Intra(); Curs[4]->Set_Not_Intra(); Curs[5]->Set_Not_Intra();}void SKL_MB::Init_Offset(){ const SKL_MP4_PIC * const Pic = VOL->Cur; const int Off = (x + y*BpS) * 8; Y1 = Pic->Y + Off * 2; U = Pic->U + Off; V = Pic->V + Off; if (Field_DCT<=0) { YBpS = BpS; Y2 = Y1 + BpS8; Field_Pred = 0; } else { SKL_ASSERT( (Y2=0, 1) ); /* sanity check */ } const int Shift = 1 + VOL->Quarter - (VOL->Reduced_VOP>0); MB_Pels = 16 << (Shift); Limit_Mins[0] = (-x*16 -16) << Shift; Limit_Maxs[0] = (-x*16+VOL->Width ) << Shift; Limit_Mins[1] = (-y*16 -16) << Shift; Limit_Maxs[1] = (-y*16+VOL->Height) << Shift; Limit_Mins_UV[0] = (-x*8 -8) << 1; Limit_Maxs_UV[0] = (-x*8+VOL->Width/2 ) << 1; Limit_Mins_UV[1] = (-y*8 -8) << 1; Limit_Maxs_UV[1] = (-y*8+VOL->Height/2) << 1;}void SKL_MB::Resync_Cursor(const SKL_MP4_I * const VOL, int New_Pos){ Start_Scan(); const int xo = New_Pos % VOL->MB_W; y = New_Pos / VOL->MB_W; Init_Scanline(VOL, xo); // mark left column/top row as invalid ("out-of-video-packet") int To_Fill = VOL->MB_W - xo; int Fill_Left = xo; if (VOL->Reduced_VOP>0) { SKL_ASSERT((y&1)==0 && (xo&1)==0); To_Fill >>= 1; Fill_Left >>= 1; } int i; for(i=0; i<2*To_Fill; ++i) // top rows Tops[0][i].Set_Not_Intra(); for(i=0; i<To_Fill; ++i) { Tops[4][i].Set_Not_Intra(); Tops[5][i].Set_Not_Intra(); } for(i=-2*Fill_Left; i<0; ++i) // left rows Curs[2][i].Set_Not_Intra(); for(i=-Fill_Left; i<0; ++i) { Curs[4][i].Set_Not_Intra(); Curs[5][i].Set_Not_Intra(); } Curs[0][-1].Set_Not_Intra(); Prev_Quant = Quant = VOL->Quant;}void SKL_MB::Init_Scanline(const SKL_MP4_I * const VOL, int xo){ // 'y' should have been initialized prior to getting here x = xo; Pos = x + y*VOL->MB_W; ABits = (Top_Ok()<<1) | (Top_Right_Ok()<<2) | 1; // left is never available. // reset left predictors to zero for(int k=0; k<4; ++k) for(int i=0; i<7; ++i) Left_ACs[k][i] = 0; int yo = y; if (VOL->Reduced_VOP>0) { yo >>= 1; xo >>= 1; } if (!VOL->Is_B_VOP()) { MVs = VOL->Cur->MV + 2*(xo + yo*MV_Stride); MVs2 = MVs + MV_Stride; } else { // sanity check MVs = 0; MVs2 = 0; } // swap the block scan lines if (!(yo&1)) { Curs[2] = VOL->Y_Preds[2] + 2*xo; Tops[0] = VOL->Y_Preds[0] + 2*xo; Tops[4] = VOL->C_Preds[0] + xo; Curs[4] = VOL->C_Preds[1] + xo; } else { Curs[2] = VOL->Y_Preds[0] + 2*xo; Tops[0] = VOL->Y_Preds[2] + 2*xo; Tops[4] = VOL->C_Preds[1] + xo; Curs[4] = VOL->C_Preds[0] + xo; } // invariants along each scan lines const int W = VOL->MB_W; Curs[0] = VOL->Y_Preds[1] + 2*xo; Curs[1] = Curs[0] + 1; Tops[2] = Curs[0]; Tops[3] = Curs[1]; Tops[1] = Tops[0] + 1; Curs[3] = Curs[2] + 1; Tops[5] = Tops[4] + W + 2; Curs[5] = Curs[4] + W + 2; Init_Offset(); // Sanity check: Boundary blocks are invariants SKL_ASSERT( VOL->Sanity_Check_Preds() );}void SKL_MB::operator++(int){ SKL_ASSERT(VOL->Reduced_VOP<=0); Tops[0] += 2; Tops[1] += 2; Tops[2] += 2; Tops[3] += 2; Tops[4] += 1; Tops[5] += 1; Curs[0] += 2; Curs[1] += 2; Curs[2] += 2; Curs[3] += 2; Curs[4] += 1; Curs[5] += 1; MVs += 2; MVs2 += 2; Y1 += 16; Y2 += 16; U += 8; V += 8; Limit_Mins[0] -= MB_Pels; Limit_Maxs[0] -= MB_Pels; Limit_Mins_UV[0] -= 16; Limit_Maxs_UV[0] -= 16; x++; Pos++; MB_Count++; ABits = ((ABits>>1) & 0x02) | (Top_Right_Ok()<<2);}#if 0 /* TODO: BROKEN FOR NOW */void SKL_MB::Next_Line_Preds(){ SKL_MB_DATA *Tmp;#define SWAP(a,b) Tmp = (a); (a) = (b); (b) = Tmp SWAP(Tops[0], Curs[2]); SWAP(Tops[4], Curs[4]); SWAP(Tops[5], Curs[5]);#undef SWAP for(int k=0; k<4; ++k) for(int i=0; i<7; ++i) Left_ACs[k][i] = 0; MVs += 4; // skip edges MVs2+= 4; // "}#endif//////////////////////////////////////////////////////////// MV prediction////////////////////////////////////////////////////////// // Map from Availability-bits to Prediction Type: // Pred Type is the following, used in descending probability: // . Median with 3 vectors // . Median with 2 vectors (!Top/!Top_Right/!Left) + zero-vector // . Copy vector (Left, Top, Top_Right) // . Zero vector
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -