?? skl_mpg4_v12.cpp
字號:
/******************************************************** * Some code. Copyright (C) 2003 by Pascal Massimino. * * All Rights Reserved. (http://skal.planet-d.net) * * For Educational/Academic use ONLY. See 'LICENSE.TXT'.* ********************************************************//* * skl_mpg4_v12.cpp * * simple, approximative, MPEG1/2 decoder * Are incorrect: oddification (MPEG1), mismatch control of * MPEG2 inter blocks. And most probably, field motion is broken, even... * Not supported: * Field frames (Bweurrrk) and of course scalable modes (who does??:). * ********************************************************/#include "./skl_mpg4i.h"//////////////////////////////////////////////////////////enum { // Start codes MPEG12_PICTURE_START = 0x00000100, MPEG12_SLICE_MIN = 0x00000101, MPEG12_SLICE_MAX = 0x000001af/* reserved = 0x000001b0 *//* reserved = 0x000001b1 */, MPEG12_USER_START = 0x000001b2, MPEG12_SEQ_START = 0x000001b3, MPEG12_SEQUENCE_ERROR = 0x000001b4, MPEG12_EXT_START = 0x000001b5/* reserved = 0x000001b6 */, MPEG12_SEQ_END = 0x000001b7, MPEG12_GOP_START = 0x000001b8, MPEG12_LAST_CODE = 0x000001ff // extension code id. (Table 6-2)., MPEG12_SEQ_EXT_ID = 1, MPEG12_SEQ_DISPLAY_EXT_ID = 2, MPEG12_QMATRIX_EXT_ID = 3, MPEG12_SEQ_SCALABLE_EXT_ID = 5, MPEG12_PIC_DISPLAY_EXT_ID = 7, MPEG12_PIC_CODING_EXT_ID = 8, MPEG12_PIC_SPATIAL_SCALABLE_EXT_ID = 9, MPEG12_PIC_TEMPORAL_SCALABLE_EXT_ID = 10 // picture structure, MPEG12_TOP_FIELD = 1, MPEG12_BOTTOM_FIELD = 2, MPEG12_FRAME_PIC = 3 // MB types, MPEG12_MBLK_ERROR = 0x00, MPEG12_MBLK_INTRA = 0x01, MPEG12_MBLK_PATTERN = 0x02, MPEG12_MBLK_MBWD = 0x04, MPEG12_MBLK_MFWD = 0x08, MPEG12_MBLK_QUANT = 0x10, MPEG12_MBLK_STWCF = 0x20 // Spatial-Temporal Weight Code Flag, MPEG12_MBLK_PSTWC = 0x40 // Permitted Spatial-Temporal Weight Class, MPEG12_MBLK_MOTION = (MPEG12_MBLK_MFWD | MPEG12_MBLK_MBWD), MPEG12_MBLK_QI = (MPEG12_MBLK_INTRA | MPEG12_MBLK_QUANT), MPEG12_MBLK_PI = (MPEG12_MBLK_INTRA | MPEG12_MBLK_PATTERN), MC_NONE = 0x000, MC_FIELD = 0x100, MC_FRAME = 0x200, MC_16x8 = 0x200, MC_DMV = 0x300 /* dual prime */, MC_ALL = 0x300};struct SKL_MB2 : public SKL_MB // special cursor for MPEG1/2{ int DC[3]; int DC_Q; int DC_Prec; SKL_MV PMV[2][2]; // [fwd/bwd][1rst pred/2nd pred] int Pic_Struct; int Concealment_MV; int Frame_Pred_DCT; const int *Scan_Order; void (*Read_Intra)(SKL_FBB*, SKL_MB2 *MB, SKL_INT16*); int (*Read_Inter)(SKL_FBB*, SKL_MB2 *MB, SKL_INT16*); SKL_FBB * const FBB; int Is_Intra() const { return ((MB_Type & MPEG12_MBLK_INTRA)!=0); } int Is_Quant() const { return ((MB_Type & MPEG12_MBLK_QUANT)!=0); } int Is_Intra_Quant() const { return ((MB_Type & MPEG12_MBLK_QI)!=0); } int Is_Intra_Pattern() const { return ((MB_Type & MPEG12_MBLK_PI)!=0); } int Is_Pattern() const { return ((MB_Type & MPEG12_MBLK_PATTERN)!=0); } int Is_Forward() const { return ((MB_Type & MPEG12_MBLK_MFWD)!=0); } int Is_Backward() const { return ((MB_Type & MPEG12_MBLK_MBWD)!=0); } int Has_Motion() const { return ((MB_Type&MPEG12_MBLK_MOTION)!=0); } int Has_B_Motion() const { return ((MB_Type&MPEG12_MBLK_MOTION)==MPEG12_MBLK_MOTION); } int Motion() const { return (MB_Type&MC_ALL); } int Is_Frame() const { return (Pic_Struct==MPEG12_FRAME_PIC); } int Has_Concealment_MV() const { return (Concealment_MV!=0); } int Is_DC_Predicted() const { return (Frame_Pred_DCT!=0); } void Reset_DC() { DC[0] = DC[1] = DC[2] = 1<<(7+DC_Prec); } void Reset_Motion_Type(); void Reset_Field_Motion_Type(); void Reset_Fwd() { SKL_ZERO_MV(PMV[0][0]); SKL_ZERO_MV(PMV[0][1]); } void Reset_Bwd() { SKL_ZERO_MV(PMV[1][0]); SKL_ZERO_MV(PMV[1][1]); } inline int MV_Outside(const SKL_MV MV) const; inline int Field_MVs_Outside(const SKL_MV MV[2]) const; void Predict_MPEG1(); void Predict_Frame(); void Predict_Fields(); void Predict_DMV(); void Predict_Reuse(); void Copy_Fwd() const { Predict_With_0MV(VOL->Copy_Ops, 1); } inline void Predict_MPEG12(const SKL_MV MVo, const SKL_MB_FUNCS * const Ops, const int CoLoc) const; inline void Predict_Fields_MPEG12(const SKL_MV MVo[2], const SKL_MB_FUNCS * const Ops, const int Src_Fields, const int CoLoc) const; int Is_MPEG1() const { return (VOL->MPEG_Version==1); } SKL_MB2(const SKL_MP4_I *vol, SKL_FBB *FBB); inline void Decode_Intra_Macroblock(); inline void Decode_Inter_Macroblock(); void Init_Scan(int yPos, int xPos) { y = yPos; if (xPos!=0) { y += xPos / VOL->MB_W; x = xPos % VOL->MB_W; } else x = 0; Init_Offset(); } int Finished() const { return (y==VOL->MB_H-1 && x==VOL->MB_W-1); } int Next() { (*this)++; if (x>=VOL->MB_W) { y++; if (y>=VOL->MB_H) return 0; // oh,oh x = 0; Init_Scanline(VOL, x); } return 1; } inline int Skip_Macroblock(int Skip); void Print_Infos() const;};//////////////////////////////////////////////////////////// VLC reading helpersstruct SKL_VLC { SKL_INT16 Value, Len; };struct SKL_DCT_VLC { SKL_INT16 Run; SKL_BYTE Level, Len; };struct SKL_VLC_CHUNK { const SKL_VLC *Tab; // <- table pointer is pre-offset SKL_UINT32 Thresh; int Shift;};struct SKL_DCT_CHUNK { const SKL_DCT_VLC *Tab; // <- table pointer is pre-offset SKL_UINT32 Thresh; int Shift;};inline static const SKL_VLC *Skl_VLC_Search(const SKL_VLC_CHUNK *Chk, SKL_UINT32 Code){ while(Code<Chk->Thresh) Chk++; SKL_ASSERT(Chk->Tab!=0); return &Chk->Tab[ Code >> Chk->Shift ];}inline static const SKL_DCT_VLC *Skl_DCT_VLC_Search(const SKL_DCT_CHUNK *Chk, SKL_UINT32 Code){ while(Code<Chk->Thresh) Chk++; SKL_ASSERT(Chk->Tab!=0); return &Chk->Tab[ Code >> Chk->Shift ];}//////////////////////////////////////////////////////////// VLC for Motion Code// ISO/IEC 13818-2 section 6.2.5// Tables B-10static const SKL_VLC MV_Tab_B10_0[14] = { { 3, 4},{-3, 4},{ 2, 3},{ 2, 3},{-2, 3},{-2, 3}, { 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{-1, 2},{-1, 2},{-1, 2},{-1, 2}};static const SKL_VLC MV_Tab_B10_1[10] = { { 7, 7},{-7, 7}, { 6, 7},{-6, 7},{ 5, 7},{-5, 7},{ 4, 6},{ 4, 6},{-4, 6},{-4, 6}};static const SKL_VLC MV_Tab_B10_2[24] = { {16,10},{-16,10},{15,10},{-15,10},{14,10},{-14,10},{13,10},{-13,10}, {12,10},{-12,10},{11,10},{-11,10},{10, 9},{10, 9},{-10, 9},{-10, 9}, { 9, 9},{ 9, 9},{-9, 9},{-9, 9},{ 8, 9},{ 8, 9},{-8, 9},{-8, 9}};static const SKL_VLC MV_Tab_B11[4] = { {0, 1}, {0,1}, { 1,2}, {-1,2}};static void Read_Motion_Vector(SKL_FBB * const Bits, SKL_INT32 Fix, SKL_INT16 &MV){ if (Bits->Get_Bits(1)) return; Bits->Check_Bits_Word(9+1); SKL_UINT32 Code = Bits->Bits; const SKL_VLC *VLC; if (Code>=0x20000000) VLC = MV_Tab_B10_0 - 2 + (Code>>(22+6)); else if (Code>=0x0c000000) VLC = MV_Tab_B10_1 - 6 + (Code>>(22+3)); else /*(Code>=0x06000000)*/ VLC = MV_Tab_B10_2 - 24 + (Code>>(22+0)); Bits->Discard(VLC->Len); const int High = 1 << (Fix+3); int Val = VLC->Value; if (--Fix) { const int Res = Bits->Get_Bits(Fix) + 1; if (Val<0) { MV += ((Val+1)<<Fix) - Res; if (MV<-High) MV += 2*High; } else { MV += ((Val-1)<<Fix) + Res; if (MV>=High) MV -= 2*High; } } else { if (Val<0) { MV += Val; if (MV<-High) MV += 2*High; } else { MV += Val; if (MV>=High) MV -= 2*High; } }}static inline int Read_DMV(SKL_FBB * const Bits){ const SKL_VLC * const VLC = &MV_Tab_B11[Bits->See_Bits(2)]; Bits->Discard(VLC->Len); return VLC->Value;}static inline void Read_Vector(SKL_FBB * const Bits, SKL_MV MV, SKL_INT32 xFCode, SKL_INT32 yFCode){ Read_Motion_Vector(Bits, xFCode, MV[0]); Read_Motion_Vector(Bits, yFCode, MV[1]);}static void Read_Motion_Vectors(SKL_MB2 *MB, int Bwd){ SKL_ASSERT(!MB->Is_MPEG1() && MB->Motion()!=MC_DMV); const int FCode = (Bwd ? MB->VOL->Bwd_Code : MB->VOL->Fwd_Code); Read_Vector(MB->FBB, MB->PMV[Bwd][0], FCode>>4, FCode&0xf); SKL_COPY_MV(MB->PMV[Bwd][1], MB->PMV[Bwd][0]); // update 2nd predictor}static inline void Read_DMV_Vector(SKL_FBB * const Bits, SKL_MV MV, SKL_MV DMV, SKL_INT32 FCode){ Read_Motion_Vector(Bits, FCode>>4, MV[0]); DMV[0] = Read_DMV(Bits); Read_Motion_Vector(Bits, FCode&0xf, MV[1]); DMV[1] = Read_DMV(Bits);}static int Read_Field_Motion_Vectors(SKL_MB2 *MB, int Bwd){ SKL_ASSERT(!MB->Is_MPEG1() && MB->Motion()!=MC_DMV); const int FCode = (Bwd ? MB->VOL->Bwd_Code : MB->VOL->Fwd_Code); int Dirs = MB->FBB->Get_Bits(1) << 1; Read_Vector(MB->FBB, MB->PMV[Bwd][0], FCode>>4, FCode&0xf); Dirs |= MB->FBB->Get_Bits(1); Read_Vector(MB->FBB, MB->PMV[Bwd][1], FCode>>4, FCode&0xf); return Dirs;}static void Read_Motion_Vectors_MPEG1(SKL_MB2 *MB, int Bwd){ const int FCode = (Bwd ? MB->VOL->Bwd_Code : MB->VOL->Fwd_Code); if (!(FCode&8)) Read_Vector(MB->FBB, MB->PMV[Bwd][0], FCode&0x7, FCode&0x7); else { // full-pix motion vector MB->PMV[Bwd][0][0] >>= 1; MB->PMV[Bwd][0][1] >>= 1; Read_Vector(MB->FBB, MB->PMV[Bwd][0], FCode&0x7, FCode&0x7); MB->PMV[Bwd][0][0] <<= 1; MB->PMV[Bwd][0][1] <<= 1; } SKL_COPY_MV(MB->PMV[Bwd][1], MB->PMV[Bwd][0]); // update 2nd predictor}void SKL_MB2::Reset_Motion_Type(){ // derive motion_type (section 6.3.17.1) SKL_ASSERT(Is_Frame()); Set_Field_DCT(-1); MB_Type &= ~MC_ALL; MB_Type |= MC_FRAME;}//////////////////////////////////////////////////////////// MPEG1-2 specific predictioninlineint SKL_MB2::MV_Outside(const SKL_MV MV) const{ return (MV[0]<Limit_Mins[0] || MV[0]>Limit_Maxs[0] || MV[1]<Limit_Mins[1] || MV[1]>Limit_Maxs[1] );}inlineint SKL_MB2::Field_MVs_Outside(const SKL_MV MV[2]) const{ return (MV[0][0]<Limit_Mins[0] || MV[0][0]>Limit_Maxs[0] || MV[1][0]<Limit_Mins[0] || MV[1][0]>Limit_Maxs[0] || 2*MV[0][1]<Limit_Mins[0] || 2*MV[0][1]>Limit_Maxs[1] || 2*MV[1][1]<Limit_Mins[0] || 2*MV[1][1]>Limit_Maxs[1] );}inlinevoid SKL_MB2::Predict_MPEG12(const SKL_MV MVo, const SKL_MB_FUNCS * const Ops, const int Fwd) const{ if (MV_Outside(MVo)) return; int Halves, Off; const int CoLoc = (Fwd ? Fwd_CoLoc : Bwd_CoLoc); SKL_BYTE * const Dst = Y1; Halves = (MVo[0]&1) | ((MVo[1]&1)<<1); Off = CoLoc + (MVo[1]>>1)*BpS + (MVo[0]>>1); Ops->HP_16x8[Halves](Dst, Dst+Off, BpS); Ops->HP_16x8[Halves](Dst+BpS8, Dst+BpS8+Off, BpS); SKL_MV uv_MV; uv_MV[0] = MVo[0] / 2; uv_MV[1] = MVo[1] / 2; Halves = (uv_MV[0]&1) | ((uv_MV[1]&1)<<1); Off = (uv_MV[1]>>1)*BpS + (uv_MV[0]>>1); Off += CoLoc; Ops->HP_8x8[Halves](U, U+Off, BpS); Ops->HP_8x8[Halves](V, V+Off, BpS);}inlinevoid SKL_MB2::Predict_Fields_MPEG12(const SKL_MV MVo[2], const SKL_MB_FUNCS * const Ops, const int Src_Fields, const int Fwd) const{ if (Field_MVs_Outside(MVo)) return; int x, y, Halves, Off; const int CoLoc = (Fwd ? Fwd_CoLoc : Bwd_CoLoc); SKL_BYTE * const Dst = Y1; // 1rst field Halves = (MVo[0][0]&1) | ((MVo[0][1]&1)<<1); Off = CoLoc + (MVo[0][1]&~1)*BpS + (MVo[0][0]>>1); if (Src_Fields&2) Off += BpS; Ops->HP_16x8[Halves](Dst, Dst+Off, 2*BpS); x = MVo[0][0] / 2; y = MVo[0][1] / 2; Halves = (x&1) | ((y&1)<<1); Off = CoLoc + (y&~1)*BpS + (x>>1); if (Src_Fields&2) Off += BpS; Ops->HP_8x4[Halves](U, U+Off, 2*BpS); Ops->HP_8x4[Halves](V, V+Off, 2*BpS); // 2nd field Halves = (MVo[1][0]&1) | ((MVo[1][1]&1)<<1); Off = CoLoc + (MVo[1][1]&~1)*BpS + (MVo[1][0]>>1); if (Src_Fields&1) Off += BpS; Ops->HP_16x8[Halves](Dst+BpS, Dst+Off, 2*BpS); x = MVo[1][0] / 2; y = MVo[1][1] / 2; Halves = (x&1) | ((y&1)<<1); Off = CoLoc + (y&~1)*BpS + (x>>1); if (Src_Fields&1) Off += BpS; Ops->HP_8x4[Halves](U+BpS, U+Off, 2*BpS); Ops->HP_8x4[Halves](V+BpS, V+Off, 2*BpS);}//////////////////////////////////////////////////////////void SKL_MB2::Predict_MPEG1(){ SKL_ASSERT(Has_Motion()); const SKL_MB_FUNCS *Ops = VOL->Copy_Ops; if (Is_Forward()) { Read_Motion_Vectors_MPEG1(this, 0); Predict_MPEG12(PMV[0][0], Ops, 1); Ops = VOL->Add_Ops; } if (Is_Backward()) { Read_Motion_Vectors_MPEG1(this, 1); Predict_MPEG12(PMV[1][0], Ops, 0); }}void SKL_MB2::Predict_Reuse(){ SKL_ASSERT(Has_Motion()); const SKL_MB_FUNCS *Ops = VOL->Copy_Ops; if (Is_Forward()) { Predict_MPEG12(PMV[0][0], Ops, 1); Ops = VOL->Add_Ops; } if (Is_Backward()) { Predict_MPEG12(PMV[1][0], Ops, 0); }}void SKL_MB2::Predict_Frame(){ SKL_ASSERT(Has_Motion()); const SKL_MB_FUNCS *Ops = VOL->Copy_Ops; if (Is_Forward()) { Read_Motion_Vectors(this, 0); Predict_MPEG12(PMV[0][0], Ops, 1); Ops = VOL->Add_Ops; } if (Is_Backward()) { Read_Motion_Vectors(this, 1); Predict_MPEG12(PMV[1][0], Ops, 0); }}void SKL_MB2::Predict_Fields(){ SKL_ASSERT(Has_Motion()); const SKL_MB_FUNCS *Ops = VOL->Copy_Ops; if (Is_Forward()) { PMV[0][0][1]>>=1; PMV[0][1][1]>>=1; int Dir = Read_Field_Motion_Vectors(this, 0); Predict_Fields_MPEG12(PMV[0], Ops, Dir, 1); PMV[0][0][1]<<=1; PMV[0][1][1]<<=1; Ops = VOL->Add_Ops; } if (Is_Backward()) { PMV[1][0][1]>>=1; PMV[1][1][1]>>=1; int Dir = Read_Field_Motion_Vectors(this, 1); Predict_Fields_MPEG12(PMV[1], Ops, Dir, 0); PMV[1][0][1]<<=1; PMV[1][1][1]<<=1; }}#define RND2(x,P) (((x)*(P)+((x)>0))>>1)void SKL_MB2::Predict_DMV() // Dual prime arithmetic (section 7.6.3.6){ SKL_ASSERT(Has_Motion() && Is_Forward() && Motion()==MC_DMV); SKL_MV dMV; SKL_MV cMV[2];
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -