?? skl_mpg4_enc.cpp
字號:
Level2 = Level1 + 1; Tbl_L1 = (Level1>=-24) ? B16_17_Code_Len[Level1^-1] : Code_Len0; Tbl_L2 = (Level2>=-24) ? B16_17_Code_Len[Level2^-1] : Code_Len0; Tbl_L1_Last = (Level1>=- 6) ? B16_17_Code_Len_Last[Level1^-1] : Code_Len0; Tbl_L2_Last = (Level2>=- 6) ? B16_17_Code_Len_Last[Level2^-1] : Code_Len0; } const SKL_UINT32 Dist1 = Lambda*dQ1*dQ1; const SKL_UINT32 Dist2 = Lambda*dQ2*dQ2; const int dDist21 = Dist2-Dist1; for(int Run=i-Run_Start; Run>0; --Run) { const SKL_UINT32 Cost_Base = Dist1 + Run_Costs[i-Run];// for sub-optimal (but slightly worth it, speed-wise) search, uncomment the following:// if (Cost_Base>=Best_Cost) continue; SKL_UINT32 Cost1, Cost2; int bLevel; Cost1 = Cost_Base + (Tbl_L1[Run-1]<<16); Cost2 = Cost_Base + (Tbl_L2[Run-1]<<16) + dDist21; if (Cost2<Cost1) { Cost1 = Cost2; bLevel = Level2; } else bLevel = Level1; if (Cost1<Best_Cost) { Best_Cost = Cost1; Nodes[i].Run = Run; Nodes[i].Level = bLevel; } Cost1 = Cost_Base + (Tbl_L1_Last[Run-1]<<16); Cost2 = Cost_Base + (Tbl_L2_Last[Run-1]<<16) + dDist21; if (Cost2<Cost1) { Cost1 = Cost2; bLevel = Level2; } else bLevel = Level1; if (Cost1<Last_Cost) { Last_Cost = Cost1; Last.Run = Run; Last.Level = bLevel; Last_Node = i; } } if (DBG==1) { Run_Costs[i] = Best_Cost; printf( "Costs #%2d: ", i); for(j=-1;j<=Non_Zero;++j) { if (j==Run_Start) printf( " %3.0d|", Run_Costs[j]>>12 ); else if (j>Run_Start && j<i) printf( " %3.0d|", Run_Costs[j]>>12 ); else if (j==i) printf( "(%3.0d)", Run_Costs[j]>>12 ); else printf( " - |" ); } printf( "<%3.0d %2d %d>", Min_Cost>>12, Nodes[i].Level, Nodes[i].Run ); printf( " Last:#%2d {%3.0d %2d %d}", Last_Node, Last_Cost>>12, Last.Level, Last.Run ); printf( " AC:%3.0d Dist0:%3d Dist(%2d):%3d Dist(%2d):%3d", AC, Dist0>>12, Level1, Dist1>>12, Level2, Dist2>>12 ); printf( "\n" ); } } else // Very very high levels, with no chance of being optimizable => Simply pick best Run. { Best_Cost = 0xf0000000; for(int Run=i-Run_Start; Run>0; --Run) { const SKL_UINT32 Cost = (30<<16) + Run_Costs[i-Run]; // 30 bits + no distortion if (Cost<Best_Cost) { Best_Cost = Cost; Nodes[i].Run = Run; Nodes[i].Level = Level1; } if (Cost<Last_Cost) { Last_Cost = Cost; Last.Run = Run; Last.Level = Level1; Last_Node = i; } } } Run_Costs[i] = Best_Cost; if (Best_Cost < Min_Cost + Dist0) { Min_Cost = Best_Cost; Run_Start = i; } else { // as noticed by Michael Niedermayer (michaelni at gmx.at), there's // a code shorter by 1 bit for a larger run (!), same level. We give // it a chance by not moving the left barrier too much. while( Run_Costs[Run_Start]>Min_Cost+(1<<16) ) Run_Start++; // spread on preceding coeffs the cost incurred by skipping this one for(j=Run_Start; j<i; ++j) Run_Costs[j] += Dist0; Min_Cost += Dist0; } } if (DBG) { Last_Cost = Evaluate_Cost(Out, Zigzag, Non_Zero, Lambda); if (DBG==1) { printf( "=> " ); for(i=0; i<=Non_Zero; ++i) printf( "[%3.0d] ", Out[Zigzag[i]] ); printf( "\n" ); } } if (Last_Node<0) return -1; // reconstruct optimal sequence backward with surviving paths SKL_BZERO(Out, 64*sizeof(*Out)); Out[Zigzag[Last_Node]] = Last.Level; i = Last_Node - Last.Run; while(i>=0) { Out[Zigzag[i]] = Nodes[i].Level; i -= Nodes[i].Run; } if (DBG) { SKL_UINT32 Cost = Evaluate_Cost(Out, Zigzag, Non_Zero, Lambda); if (DBG==1) { printf( "<= " ); for(i=0; i<=Last_Node; ++i) printf( "[%3.0d] ", Out[Zigzag[i]] ); printf( "\n--------------------------------\n" ); } if (Cost>Last_Cost) printf( "!!! %d > %d\n", Cost, Last_Cost ); } return Last_Node;}#undef DBG////////////////////////////////////////////////////////////// Main decimation calls////////////////////////////////////////////////////////////void SKL_MP4_ENC_I::Decimate_Intra(SKL_INT16 * const Out, SKL_INT16 * const In, SKL_INT32 Q, SKL_INT32 DC_Q) const{ Quant_Ops.Dct(In); Quant_Ops.Quant_Intra(Out, In, Q_Intra, Q, DC_Q);// this is WRONG 2 out of 3 times, due to DC/AC prediction// if (_Use_Trellis && Trellis_Quantize(Out, Q, SKL_MP4_I::Scan_Order[0]+1, 62)<0)// return; Quant_Ops.Dequant_Intra(In, Out, Q_Intra, Q, DC_Q);}int SKL_MP4_ENC_I::Decimate_Inter(SKL_INT16 * const Out, SKL_INT16 * const In, const SKL_INT32 Q) const{ Quant_Ops.Dct(In); int SAV = Quant_Ops.Quant_Inter(Out, In, Q_Inter, Q); if (SAV<_Inter_Coding_Threshold) return 0; if (_Use_Trellis && Trellis_Quantize(Out, Q, SKL_MP4_I::Scan_Order[0], 63)<0) return 0; Quant_Ops.Dequant_Inter(In, Out, Q_Inter, Q, 0xff); return SAV;}//////////////////////////////////////////////////////////// Macroblock params polishing//////////////////////////////////////////////////////////const int SKL_MB_ENC::Map_To_Type[SKL_MAP_LAST] ={ SKL_MB_SKIPPED, SKL_MB_INTRA, SKL_MB_INTER /*(GMC)*/, SKL_MB_INTER, SKL_MB_INTER, SKL_MB_INTER4V};static inline void Set_dMV(SKL_MV dMV, const SKL_MV MVo){ // dMV contains predictor dMV[0] = MVo[0] - dMV[0]; dMV[1] = MVo[1] - dMV[1];}void SKL_MB_ENC::Substract_Prediction(){ SKL_ASSERT(MB_Type<=SKL_MB_INTER4V && Field_Pred==0); // INTER or INTER4V Predict_Motion_Vector_Blk0( dMVs[0], &MVs[0], MVs-1 ); Set_dMV(dMVs[0], MVs[0]); if (MB_Type==SKL_MB_INTER4V) { Predict_Motion_Vector( dMVs[1], &MVs[1], 1 ); Set_dMV(dMVs[1], MVs[ 1]); Predict_Motion_Vector( dMVs[2], &MVs2[0], 2 ); Set_dMV(dMVs[2], MVs2[0]); Predict_Motion_Vector( dMVs[3], &MVs2[1], 3 ); Set_dMV(dMVs[3], MVs2[1]); }}void SKL_MB_ENC::Substract_Field_Prediction(){ SKL_ASSERT(MB_Type<SKL_MB_INTER4V && Field_Pred==1); // INTER+field only Predict_Motion_Vector_Blk0( dMVs[0], &MVs[0], MVs-1 ); dMVs[0][1] /= 2; // Both fields use the same predictor MVs[0][1] >>= 1; // descale to field-MV... MVs[1][1] >>= 1; // Scale will be restored after coding. SKL_COPY_MV(dMVs[1], dMVs[0]); Set_dMV(dMVs[0], MVs[0]); Set_dMV(dMVs[1], MVs[1]);}void SKL_MB_ENC::Set_Final_Params(){ // update dQ if (Map[Pos].dQ) { dQuant = Map[Pos].dQ; Prev_Quant = Quant; Quant += dQuant; SKL_ASSERT(Quant>=1 && Quant<=31); } else dQuant = 0; // set up field params if (VOL->Interlace) { if (VOL->Interlace&0x3) Set_Field_DCT( (Map[Pos].Flags&1)!=0 ); else SKL_ASSERT(Field_DCT==0); if (VOL->Interlace&0xc) { if (Map[Pos].Type==SKL_MAP_16x8) { Field_Pred = 1; Field_Dir = ((MVs[0][1]&1)<<1) | ((MVs[1][1]&1)^1); Substract_Field_Prediction(); } else Field_Pred = 0; } else SKL_ASSERT(Field_Pred==0); } else SKL_ASSERT(Field_DCT==-1 && Field_Pred==0); if (MB_Type!=SKL_MB_INTRA && !MC_Sel && !Field_Pred) Substract_Prediction();}//////////////////////////////////////////////////////////// I-MB codingvoid SKL_MB_ENC::Encode_Intra(SKL_FBB * const Bits, SKL_INT16 In[12*64], int Is_I_VOP){ SKL_INT16 *C; int blk; const int * Zigzags[6]; int Pred_Dirs[6]; Use_AC_Pred = Select_DC_AC_Pred(In, Pred_Dirs); Cbp = 0; C = In; for(blk=0; blk<6; ++blk) { Zigzags[blk] = Use_AC_Pred ? SKL_MP4_I::Scan_Order[Pred_Dirs[blk]] : SKL_MP4_I::Scan_Order[0]; Last[blk] = Find_Last(C, Zigzags[blk], 63); Cbp <<= 1; if (Last[blk]>0) Cbp |= 1; C += 64; } // time to really set the MB_Type if (dQuant!=0) { SKL_ASSERT(MB_Type!=SKL_MB_INTER4V); MB_Type += 1; // INTRA->INTRA_Q or INTER->INTER_Q } const SKL_VLC *VLC; if (Is_I_VOP) VLC = &MCBPC_Intra_B6[ MB_Type-3 ][ Cbp & 3 ]; else VLC = &MCBPC_Inter_B7[ MB_Type ][ Cbp & 3 ]; Bits->Put_Bits( VLC->Val, VLC->Len ); Bits->Put_Bits( Use_AC_Pred, 1 ); int CbpY = Cbp >> 2; if (MB_Type<=SKL_MB_INTER_Q) CbpY ^= 0x0f; VLC = &CBPY_B8[ CbpY ]; Bits->Put_Bits( VLC->Val, VLC->Len ); if (dQuant!=0) { /* INTRA_Q or INTER_Q */ SKL_ASSERT(dQuant>=-2 && dQuant<=2); Bits->Put_Bits( DQuant_Tab[dQuant+2], 2 ); } if (Field_DCT>=0) // interlace? Bits->Put_Bits( Field_DCT, 1 ); const SKL_SAFE_INT Pos2 = Bits->Write_Bit_Pos(); C = In; for(blk=0; blk<6; ++blk) { // TODO: DC_Thresh here... Write_DC_Coeff(Bits, C[0], (blk<4)); // DC-coeff if (Last[blk]>0) Write_Coeffs( Bits, C, Zigzags[blk]+1, Last[blk]-1, B16_17_Tabs[1]); C += 64; } Texture_Bits += Bits->Write_Bit_Pos() - Pos2; Store_Zero_MV();}//////////////////////////////////////////////////////////// P-MB codingvoid SKL_MB_ENC::Encode_Inter(SKL_FBB * const Bits, SKL_INT16 In[12*64], int Fwd_Code){ SKL_ASSERT(MB_Type <= SKL_MB_INTER4V); // time to really set the MB_Type if (dQuant!=0) { SKL_ASSERT(MB_Type<SKL_MB_INTER4V); MB_Type = SKL_MB_INTER_Q; } const SKL_VLC *VLC; VLC = &MCBPC_Inter_B7[ MB_Type ][ Cbp & 3 ]; Bits->Put_Bits( VLC->Val, VLC->Len ); if (MB_Type<=SKL_MB_INTER_Q && VOL->Is_S_VOP() && VOL->Sprite_Mode==SPRITE_GMC) Bits->Put_Bits(MC_Sel, 1); VLC = &CBPY_B8[ (Cbp>>2) ^ 0xf ]; Bits->Put_Bits( VLC->Val, VLC->Len ); if (dQuant!=0) { /* INTER_Q */ SKL_ASSERT(dQuant>=-2 && dQuant<=2); Bits->Put_Bits( DQuant_Tab[dQuant+2], 2 ); } if (Field_DCT>=0) // interlace? (this costs 0.1% in file size) { if (Cbp!=0) Bits->Put_Bits( Field_DCT, 1 ); if (MB_Type<=SKL_MB_INTER_Q && !MC_Sel) /* INTER or INTER_Q */ { Bits->Put_Bits( Field_Pred, 1 ); if (Field_Pred) Bits->Put_Bits( Field_Dir&3, 2 ); // Fwd Top/Bottom field select. } // Note: no field pred for INTER4V or INTRA, or GMC } if (!MC_Sel) // no vector for GMC { const SKL_SAFE_INT Pos = Bits->Write_Bit_Pos(); Write_Vector(Bits, dMVs[0], Fwd_Code); if (MB_Type==SKL_MB_INTER4V) { Write_Vector(Bits, dMVs[1], Fwd_Code); Write_Vector(Bits, dMVs[2], Fwd_Code); Write_Vector(Bits, dMVs[3], Fwd_Code); } else /* INTER or INTER_Q */ { if (Field_Pred) Write_Vector(Bits, dMVs[1], Fwd_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();}//////////////////////////////////////////////////////////// B-MB codingvoid SKL_MB_ENC::Encode_Inter_B(SKL_FBB * const Bits, SKL_INT16 In[12*64], int Fwd_Code, int Bwd_Code){ int ModB1 = (B_Type==SKL_MB_DIRECT && dMVs[0][0]==0 && dMVs[0][1]==0); if (Cbp==0) { if (ModB1) Bits->Put_Bits( 1, 1 ); // ModB1 else Bits->Put_Bits( 1, 2 ); // ModB2 } else { Bits->Put_Bits( 0, 2 ); // ModB1/B2 Bits->Put_Bits( Cbp, 6 ); if (B_Type!=SKL_MB_DIRECT) { if (dQuant==-2) Bits->Put_Bits( 2, 2 ); else if (dQuant==2) Bits->Put_Bits( 3, 2 ); else { SKL_ASSERT(dQuant==0); Bits->Put_Bits( 0, 1 ); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -