📄 mbtransquant.c
字号:
dQ2 = dQ1 + Mult; 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; } Dist1 = Lambda*dQ1*dQ1; Dist2 = Lambda*dQ2*dQ2; dDist21 = Dist2-Dist1; for(Run=i-Run_Start; Run>0; --Run) { const uint32_t Cost_Base = Dist1 + Run_Costs[i-Run]; uint32_t Cost1, Cost2; int bLevel; /* for sub-optimal (but slightly worth it, speed-wise) search, * uncomment the following: * if (Cost_Base>=Best_Cost) continue; * (? doesn't seem to have any effect -- gruel ) */ Cost1 = Cost_Base + (Tbl_L1[Run-1]<<TL_SHIFT); Cost2 = Cost_Base + (Tbl_L2[Run-1]<<TL_SHIFT) + 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]<<TL_SHIFT); Cost2 = Cost_Base + (Tbl_L2_Last[Run-1]<<TL_SHIFT) + 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; } } /* end of "for Run" */ } else { /* Very very high levels, with no chance of being optimizable * => Simply pick best Run. */ int Run; for(Run=i-Run_Start; Run>0; --Run) { /* 30 bits + no distortion */ const uint32_t Cost = (30<<TL_SHIFT) + Run_Costs[i-Run]; 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<<TL_SHIFT) ) 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; } } /* It seems trellis doesn't give good results... just leave the block untouched * and return the original sum value */ if (Last_Node<0) return Sum; /* reconstruct optimal sequence backward with surviving paths */ memset(Out, 0x00, 64*sizeof(*Out)); Out[Zigzag[Last_Node]] = Last.Level; i = Last_Node - Last.Run; Sum = abs(Last.Level); while(i>=0) { Out[Zigzag[i]] = Nodes[i].Level; Sum += abs(Nodes[i].Level); i -= Nodes[i].Run; } return Sum;}/* original version including heavy debugging info */#ifdef DBGTRELL#define DBG 0static __inline uint32_t Evaluate_Cost(const int16_t *C, int Mult, int Bias, const uint16_t * Zigzag, int Max, int Lambda){#if (DBG>0) const int16_t * const Ref = C + 6*64; int Last = Max; int Bits = 0; int Dist = 0; int i; uint32_t Cost; while(Last>=0 && C[Zigzag[Last]]==0) Last--; if (Last>=0) { int j=0, j0=0; int Run, Level; Bits = 2; /* CBP */ while(j<Last) { while(!C[Zigzag[j]]) j++; if (j==Last) break; Level=C[Zigzag[j]]; Run = j - j0; j0 = ++j; if (Level>=-24 && Level<=24) Bits += B16_17_Code_Len[(Level<0) ? -Level-1 : Level-1][Run]; else Bits += 30; } Level = C[Zigzag[Last]]; Run = j - j0; if (Level>=-6 && Level<=6) Bits += B16_17_Code_Len_Last[(Level<0) ? -Level-1 : Level-1][Run]; else Bits += 30; } for(i=0; i<=Last; ++i) { int V = C[Zigzag[i]]*Mult; if (V>0) V += Bias; else if (V<0) V -= Bias; V -= Ref[Zigzag[i]]; Dist += V*V; } Cost = Lambda*Dist + (Bits<<TL_SHIFT); if (DBG==1) printf( " Last:%2d/%2d Cost = [(Bits=%5.0d) + Lambda*(Dist=%6.0d) = %d ] >>12= %d ", Last,Max, Bits, Dist, Cost, Cost>>12 ); return Cost;#else return 0;#endif}static intdct_quantize_trellis_h263_c(int16_t *const Out, const int16_t *const In, int Q, const uint16_t * const Zigzag, int Non_Zero){ /* * Note: We should search last non-zero coeffs on *real* DCT input coeffs (In[]), * not quantized one (Out[]). However, it only improves the result *very* * slightly (~0.01dB), whereas speed drops to crawling level :) * Well, actually, taking 1 more coeff past Non_Zero into account sometimes helps. */ typedef struct { int16_t Run, Level; } NODE; NODE Nodes[65], Last; uint32_t Run_Costs0[64+1]; uint32_t * const Run_Costs = Run_Costs0 + 1; const int Mult = 2*Q; const int Bias = (Q-1) | 1; const int Lev0 = Mult + Bias; const int Lambda = Trellis_Lambda_Tabs[Q-1]; /* it's 1/lambda, actually */ int Run_Start = -1; Run_Costs[-1] = 2<<TL_SHIFT; /* source (w/ CBP penalty) */ uint32_t Min_Cost = 2<<TL_SHIFT; int Last_Node = -1; uint32_t Last_Cost = 0; int i, j;#if (DBG>0) Last.Level = 0; Last.Run = -1; /* just initialize to smthg */#endif Non_Zero = Find_Last(Out, Zigzag, Non_Zero); if (Non_Zero<0) return -1; for(i=0; i<=Non_Zero; i++) { const int AC = In[Zigzag[i]]; const int Level1 = Out[Zigzag[i]]; const int Dist0 = Lambda* AC*AC; uint32_t Best_Cost = 0xf0000000; Last_Cost += Dist0; if ((uint32_t)(Level1+1)<3) /* very specialized loop for -1,0,+1 */ { int dQ; int Run; uint32_t Cost0; if (AC<0) { Nodes[i].Level = -1; dQ = Lev0 + AC; } else { Nodes[i].Level = 1; dQ = Lev0 - AC; } Cost0 = Lambda*dQ*dQ; Nodes[i].Run = 1; Best_Cost = (Code_Len20[0]<<TL_SHIFT) + Run_Costs[i-1]+Cost0; for(Run=i-Run_Start; Run>0; --Run) { const uint32_t Cost_Base = Cost0 + Run_Costs[i-Run]; const uint32_t Cost = Cost_Base + (Code_Len20[Run-1]<<TL_SHIFT); const uint32_t lCost = Cost_Base + (Code_Len24[Run-1]<<TL_SHIFT); /* * TODO: what about tie-breaks? Should we favor short runs or * long runs? Although the error is the same, it would not be * spread the same way along high and low frequencies... */ if (Cost<Best_Cost) { Best_Cost = Cost; Nodes[i].Run = Run; } if (lCost<Last_Cost) { Last_Cost = lCost; Last.Run = Run; Last_Node = i; } } if (Last_Node==i) Last.Level = Nodes[i].Level; 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(%d)=%d", AC, Dist0>>12, Nodes[i].Level, Cost0>>12 ); printf( "\n" ); } } else /* "big" levels */ { const uint8_t *Tbl_L1, *Tbl_L2, *Tbl_L1_Last, *Tbl_L2_Last; int Level2; int dQ1, dQ2; int Run; uint32_t Dist1,Dist2; int dDist21; if (Level1>1) { dQ1 = Level1*Mult-AC + Bias; dQ2 = dQ1 - Mult; 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; } else { /* Level1<-1 */ dQ1 = Level1*Mult-AC - Bias; dQ2 = dQ1 + Mult; 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; } Dist1 = Lambda*dQ1*dQ1; Dist2 = Lambda*dQ2*dQ2; dDist21 = Dist2-Dist1; for(Run=i-Run_Start; Run>0; --Run) { const uint32_t Cost_Base = Dist1 + Run_Costs[i-Run]; uint32_t Cost1, Cost2; int bLevel;/* * for sub-optimal (but slightly worth it, speed-wise) search, uncomment the following: * if (Cost_Base>=Best_Cost) continue; */ Cost1 = Cost_Base + (Tbl_L1[Run-1]<<TL_SHIFT); Cost2 = Cost_Base + (Tbl_L2[Run-1]<<TL_SHIFT) + 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]<<TL_SHIFT); Cost2 = Cost_Base + (Tbl_L2_Last[Run-1]<<TL_SHIFT) + 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; } } /* end of "for Run" */ 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" ); } } 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<<TL_SHIFT) ) 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,Mult,Bias, 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 */ memset(Out, 0x00, 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) { uint32_t Cost = Evaluate_Cost(Out,Mult,Bias, 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( "!!! %u > %u\n", Cost, Last_Cost ); } return Last_Node;}#undef DBG#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -