📄 skl_mpg4_dec.cpp
字号:
// I-framevoid SKL_MB::Decode_Intra_Infos(SKL_FBB * const Bits){ const SKL_VLC *VLC; while(Bits->See_Bits(9)==1) Bits->Discard(9); // MCBPC stuffing VLC = &MCBPC_Intra_B6_0[Bits->See_Bits(6)-1]; Bits->Discard(VLC->Len); MB_Type = VLC->Val >> 2; Cbp = VLC->Val & 3; // Cbpc Use_AC_Pred = Bits->Get_Bits(1); VLC = &CBPY_Tab[Bits->See_Bits(6)-2]; Bits->Discard(VLC->Len); Cbp |= VLC->Val; if (MB_Type==SKL_MB_INTRA_Q) { Prev_Quant = Quant; Quant += DQuant_Tab[ Bits->Get_Bits(2) ]; if (Quant>31) Quant = 31; else if (Quant< 1) Quant = 1; } if (Field_DCT>=0) Set_Field_DCT( Bits->Get_Bits(1) ); else { SKL_ASSERT(Field_DCT==-1 && Field_Pred==0); }}static void Read_I_VOP(SKL_FBB * const Bits, const SKL_MP4_I * const VOP){ SKL_MB MB(VOP); SKL_INT16 Base[7*64+SKL_ALIGN]; SKL_INT16 * const In = (SKL_INT16*)SKL_ALIGN_PTR(Base, SKL_ALIGN); while(MB.y<VOP->MB_H) { MB.Init_Scanline(VOP, 0); while(MB.x<VOP->MB_W) { MB.Decode_Intra_Infos(Bits); MB.Decode_Intra_Blocks(Bits, In, VOP); MB.Copy_16To8(In+1*64); MB.Store_Map_Infos(); MB.Store_Zero_MV(); if (!MB.Resync || !MB.Resync_Marker(Bits)) MB++; if (VOP->Debug_Level==5) { printf( "%c", "*-="[1+MB.Field_DCT] ); if (MB.x==VOP->MB_W) { printf( "\n" ); if (MB.y==VOP->MB_H-1) printf( "\n" ); } } } if (VOP->Debug_Level==2) VOP->Dump_Line(0, &MB); if (VOP->Slicer) VOP->Slicer(VOP->Cur, MB.y*16, 16, VOP->Slicer_Data); MB.y++; }}//////////////////////////////////////////////////////////// P-framevoid SKL_MB::Decode_Inter_Infos(SKL_FBB * const Bits, const SKL_MV * const Left_Predictor){ while(Bits->See_Bits(10)==1) Bits->Discard(10); // MCBPC stuffing const SKL_VLC *VLC; // Chroma MB type and block pattern if (Bits->Get_Bits(1)) // test leading bit first VLC = &MCBPC_Inter_B7_0[0]; else { Bits->Check_Bits(8); const SKL_UINT32 Code = Bits->Bits; if (Code>=0x30000000) VLC = MCBPC_Inter_B7_0 - 3+1 + (Code>>(24+4)); else /* if (Code>=0x02000000) */ VLC = MCBPC_Inter_B7_1 - 2 + (Code>>(24+0)); Bits->Discard(VLC->Len); } MB_Type = VLC->Val >> 2; Cbp = VLC->Val & 3; // Cbpc if (MB_Type >= SKL_MB_INTRA) /* INTRA or INTRA_Q */ Use_AC_Pred = Bits->Get_Bits(1); else { Use_AC_Pred = 0; Cbp |= 0x0f<<2; if (MB_Type<=SKL_MB_INTER_Q && VOL->Is_S_VOP() && VOL->Sprite_Mode==SPRITE_GMC) MC_Sel = Bits->Get_Bits(1); else MC_Sel = 0; } VLC = &CBPY_Tab[ Bits->See_Bits(6)-2 ]; // block pattern for luminance Bits->Discard(VLC->Len); Cbp ^= VLC->Val; if (MB_Type==SKL_MB_INTER_Q || MB_Type==SKL_MB_INTRA_Q) { Prev_Quant = Quant; Quant += DQuant_Tab[ Bits->Get_Bits(2) ]; if (Quant>31) Quant = 31; // TODO: should be quant_prec here else if (Quant< 1) Quant = 1; } if (Field_DCT>=0) // <- equivalent to testing 'VOL->Interlace' { if (MB_Type<=SKL_MB_INTER_Q && !MC_Sel) /* INTER or INTER_Q */ { int DCT = (Cbp!=0) ? (int)Bits->Get_Bits(1) : 0; Set_Field_DCT( DCT ); Field_Pred = Bits->Get_Bits(1); if (Field_Pred) Field_Dir = (Field_Dir&~0x03) | Bits->Get_Bits(2); // top/bottom } else { Field_Pred = 0; if (MB_Type>=SKL_MB_INTRA || Cbp!=0) // for INTRA in P-VOP or INTER4V Set_Field_DCT( Bits->Get_Bits(1) ); else Set_Field_DCT( 0 ); } } else { SKL_ASSERT(Field_DCT==-1 && Field_Pred==0); } if (MB_Type<=SKL_MB_INTER4V && !MC_Sel) { Predict_Motion_Vector_Blk0( MVs[0], &MVs[0], Left_Predictor ); if (!Field_Pred) { Read_Vector( Bits, VOL->Fwd_Code, MVs[0] ); if (MB_Type==SKL_MB_INTER4V) { Predict_Motion_Vector( MVs[1], &MVs[1], 1 ); Read_Vector( Bits, VOL->Fwd_Code, MVs[1] ); Predict_Motion_Vector( MVs2[0], &MVs2[0], 2 ); Read_Vector( Bits, VOL->Fwd_Code, MVs2[0] ); Predict_Motion_Vector( MVs2[1], &MVs2[1], 3 ); Read_Vector( Bits, VOL->Fwd_Code, MVs2[1] ); } } else { MVs[0][1] /= 2; // see section 7.7.2.1 SKL_COPY_MV(MVs[1], MVs[0]); // Both fields use the same predictor Read_Vector( Bits, VOL->Fwd_Code, MVs[0] ); Read_Vector( Bits, VOL->Fwd_Code, MVs[1] ); } }}static void Read_P_VOP(SKL_FBB * const Bits, const SKL_MP4_I * const VOP){ SKL_MB MB(VOP); SKL_INT16 Base[7*64+SKL_ALIGN]; SKL_INT16 * const In = (SKL_INT16*)SKL_ALIGN_PTR(Base, SKL_ALIGN); while(MB.y<VOP->MB_H) { MB.Init_Scanline(VOP, 0); const SKL_MV *Left_Predictor = 0; while(MB.x<VOP->MB_W) { if (Bits->Get_Bits(1)) // not coded { MB.MC_Sel = (VOP->Is_S_VOP() && VOP->Sprite_Mode==SPRITE_GMC); if (!MB.MC_Sel) { MB.MB_Type = SKL_MB_SKIPPED; MB.Predict_With_0MV(VOP->Copy_Ops, 1); MB.Store_Zero_MV(); } else { MB.MB_Type = SKL_MB_INTER; // skipped GMC mb are not really 'skipped' MB.Predict_GMC(); // 16x16 mode } MB.Set_Not_Intra(); Left_Predictor = &MB.MVs[1]; } else { MB.Decode_Inter_Infos(Bits, Left_Predictor); if (MB.MB_Type >= SKL_MB_INTRA) /* INTRA or INTRA_Q */ { MB.Decode_Intra_Blocks(Bits, In, VOP); MB.Copy_16To8(In+1*64); MB.Store_Zero_MV(); Left_Predictor = &MB.MVs[1]; } else { MB.Decode_Inter_Blocks(Bits, In, VOP); MB.Set_Not_Intra(); if (MB.MC_Sel) { MB.MB_Type = SKL_MB_INTER; MB.Predict_GMC(); // 16x16 mode Left_Predictor = &MB.MVs[1]; } else { if (MB.MB_Type != SKL_MB_INTER4V) /* INTER or INTER_Q */ { if (!MB.Field_Pred) { MB.Predict_With_1MV(MB.MVs[0], VOP->Copy_Ops, 1); MB.Store_16x16_MV(); // 16x16 mode Left_Predictor = &MB.MVs[1]; } else { // Impl: we don't multiply the final field // vectors by 2 (cf. Store_16x8_MV()) MB.Predict_Fields(MB.MVs, VOP->Copy_Ops, 1, MB.Field_Dir); MB.Store_16x8_MV(&MB.MVs2[0], &MB.MVs[0]); // field MV mode Left_Predictor = &MB.MVs2[1]; // wow! } } else /* INTER4V */ { MB.Predict_With_4MV(MB.MVs, MB.MVs2, VOP->Copy_Ops, 1); Left_Predictor = &MB.MVs[1]; } } MB.Add_16To8(In + 1*64); } } MB.Store_Map_Infos(); if (!MB.Resync || !MB.Resync_Marker(Bits)) MB++; if (VOP->Debug_Level==5) { if (MB.MC_Sel==1) printf( MB.MB_Type==SKL_MB_SKIPPED ? "G" : "g" ); else if (MB.MB_Type==SKL_MB_SKIPPED) printf( "s" ); else if (MB.Field_Pred==1) printf( "=" ); else if (MB.MB_Type==SKL_MB_INTER4V) printf( "4" ); else if (MB.MB_Type>=SKL_MB_INTRA) printf( "*" ); else printf( "%c", ".-="[1+MB.Field_DCT] ); if (MB.x==VOP->MB_W) { printf( "\n" ); if (MB.y==VOP->MB_H-1) printf( "\n" ); } } } if (VOP->Debug_Level==2) VOP->Dump_Line(0, &MB); if (VOP->Slicer) VOP->Slicer(VOP->Cur, MB.y*16, 16, VOP->Slicer_Data); MB.y++; } if (VOP->Debug_Level==1) { if (VOP->Is_S_VOP()) VOP->Draw_GMC(VOP->Cur); VOP->Dump_MVs(VOP->Cur, 2); }}//////////////////////////////////////////////////////////// B-framestatic void Read_B_VOP(SKL_FBB * const Bits, const SKL_MP4_I * const VOP){ SKL_ASSERT(VOP->Rounding==0); // Note: at this point, due to re-ordering, the Past frame // is VOP->Future and the future one be VOP->Past! SKL_MP4_PIC * const Cur = VOP->Cur; const SKL_MP4_PIC * const Next = VOP->Future; const SKL_MP4_PIC * const Prev = VOP->Past; // Note: we don't store the Map[] values for B-VOPs, // but we need the future Map const SKL_MP4_MAP * const Map = Next->Map; SKL_ASSERT(Map!=0); const int Trb = (int)( Cur->Time_Ticks - VOP->Time_Last_Coded ); const int Trd = (int)( Next->Time_Ticks - VOP->Time_Last_Coded ); int Trbf = 0, Trdf = 0; SKL_MB MB(VOP); const int S = VOP->MV_Stride; while(MB.y<VOP->MB_H) { // note: MVs are not used nor stored for B-VOPs // 4 special predictors are used, except for MB_DIRECT // They are resetted at start of new row // Indexes: #0/1: fwd frame/field preds. #2/3: bwd preds SKL_MV Preds[4] = { {0,0}, {0,0}, {0,0}, {0,0} }; MB.Init_Scanline(VOP, 0); while(MB.x<VOP->MB_W) { if ( Map[MB.Pos].Type==SKL_MAP_SKIPPED ) // skipped in the future? { // we don't need no MV. Simply copy. MB.Cbp = 0; MB.Set_No_Field(); MB.Predict_With_0MV(VOP->Copy_Ops, 1); if (VOP->Debug_Level==5) { printf( "s" ); if (MB.x==VOP->MB_W-1) { printf( "\n" ); if (MB.y==VOP->MB_H-1) printf( "\n" ); } } } else { int B_Type; int ModB1 = Bits->Get_Bits(1); // ModeB (hardcoded table B-3) if (ModB1) { MB.Cbp = 0; B_Type = SKL_MB_DIRECT; MB.Set_No_Field(); } else { const int ModB2 = Bits->Get_Bits(1); const SKL_VLC *VLC = &BType_Tab_B4[Bits->See_Bits(4) - 1]; B_Type = VLC->Val; Bits->Discard( VLC->Len ); MB.Cbp = ModB2 ? 0 : Bits->Get_Bits(6); if ( B_Type!=SKL_MB_DIRECT && MB.Cbp!=0 ) { if (Bits->Get_Bits(1)) { MB.Prev_Quant = MB.Quant; MB.Quant += DBQuant_Tab[ Bits->Get_Bits(1) + 2 ]; if (MB.Quant>31) MB.Quant = 31; // TODO: should be quant_prec here else if (MB.Quant< 1) MB.Quant = 1; } } if (MB.Field_DCT>=0) { MB.Set_Field_DCT( MB.Cbp ? (int)Bits->Get_Bits(1) : 0 ); if (B_Type!=SKL_MB_DIRECT) { MB.Field_Pred = Bits->Get_Bits(1); if (MB.Field_Pred) { if (B_Type!=SKL_MB_BWD) MB.Field_Dir = (MB.Field_Dir&~0x03) | Bits->Get_Bits(2); if (B_Type!=SKL_MB_FWD) MB.Field_Dir = (MB.Field_Dir&~0x0c) | (Bits->Get_Bits(2) << 2); } } else { MB.Field_Pred = 0; } } else SKL_ASSERT(MB.Field_DCT==-1 && MB.Field_Pred==0); } // here we go for the predictions if (B_Type==SKL_MB_DIRECT) // Grrrr! { SKL_MV dMV = {0,0}; if (!ModB1) // need a differential MV? Read_Vector( Bits, 1, dMV ); // FCode=1, always. // interpolate the 4 bwd/fwd vectors (section 7.6.9.5.2) const int Offset = 2 * (MB.x + MB.y*S); const SKL_MV * const Ref = Next->MV + Offset; SKL_MV MVs[8]; // no need to store the MVs => use local var if (Map[MB.Pos].Type!=SKL_MAP_16x8) { MVs[0][0] = dMV[0] + (SKL_INT16)( Trb*Ref[0][0]/Trd ); MVs[0][1] = dMV[1] + (SKL_INT16)( Trb*Ref[0][1]/Trd ); if (dMV[0]==0) MVs[4][0] = (SKL_INT16)( (Trb-Trd)*Ref[0][0]/Trd ); else MVs[4][0] = MVs[0][0] - Ref[0][0]; if (dMV[1]==0) MVs[4][1] = (SKL_INT16)( (Trb-Trd)*Ref[0][1]/Trd ); else MVs[4][1] = MVs[0][1] - Ref[0][1]; if (Map[MB.Pos].Type==SKL_MAP_16x16) { if (!VOP->Quarter) { MB.Predict_With_1MV(MVs[0], VOP->Copy_Ops, 1); MB.Predict_With_1MV(MVs[4], VOP->Add_Ops, 0); } else { // For QPel, because of mirroring, we must split // the 16x16 block into four 8x8 ones. SKL_COPY_MV(MVs[1], MVs[0]); SKL_COPY_MV(MVs[2], MVs[0]); SKL_COPY_MV(MVs[3], MVs[0]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -