--- vop_type_decision.c 2003/09/10 22:19:00 1.1.2.1 +++ vop_type_decision.c 2003/12/04 12:08:03 1.1.2.6 @@ -19,7 +19,7 @@ * along with this program ; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: vop_type_decision.c,v 1.1.2.1 2003/09/10 22:19:00 edgomez Exp $ + * $Id: vop_type_decision.c,v 1.1.2.6 2003/12/04 12:08:03 syskin Exp $ * ****************************************************************************/ @@ -33,12 +33,21 @@ #include "motion_inlines.h" -#define INTRA_THRESH 2200 +#define INTRA_THRESH 2000 #define INTER_THRESH 40 -#define INTRA_THRESH2 95 +#define INTRA_THRESH2 90 + +/* when we are in 1/I_SENS_TH before forced keyframe, we start to decrese i-frame threshold */ +#define I_SENS_TH 3 + +/* how much we subtract from each p-frame threshold for 2nd, 3rd etc. b-frame in a row */ +#define P_SENS_BIAS 18 + +/* .. but never below INTER_THRESH_MIN */ +#define INTER_THRESH_MIN 5 static void -CheckCandidate32I(const int x, const int y, const SearchData * const data, const unsigned int Direction) +CheckCandidate32I(const int x, const int y, SearchData * const data, const unsigned int Direction) { /* maximum speed */ int32_t sad; @@ -52,7 +61,7 @@ if (sad < *(data->iMinSAD)) { *(data->iMinSAD) = sad; data->currentMV[0].x = x; data->currentMV[0].y = y; - *data->dir = Direction; + data->dir = Direction; } if (data->temp[0] < data->iMinSAD[1]) { data->iMinSAD[1] = data->temp[0]; data->currentMV[1].x = x; data->currentMV[1].y = y; } @@ -115,7 +124,7 @@ CheckCandidate32I(pmv[2].x, pmv[2].y, Data, 2); if (*Data->iMinSAD > 500) { /* diamond only if needed */ - unsigned int mask = make_mask(pmv, 3, *Data->dir); + unsigned int mask = make_mask(pmv, 3, Data->dir); xvid_me_DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, mask, CheckCandidate32I); } else simplicity++; @@ -137,42 +146,44 @@ MEanalysis( const IMAGE * const pRef, const FRAMEINFO * const Current, const MBParam * const pParam, - const int maxIntra, //maximum number if non-I frames - const int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame - const int bCount, // number of B frames in a row - const int b_thresh) + const int maxIntra, /* maximum number if non-I frames */ + const int intraCount, /* number of non-I frames after last I frame; 0 if we force P/B frame */ + const int bCount, /* number of B frames in a row */ + const int b_thresh, + const MACROBLOCK * const prev_mbs) { uint32_t x, y, intra = 0; int sSAD = 0; MACROBLOCK * const pMBs = Current->mbs; const IMAGE * const pCurrent = &Current->image; - int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH + b_thresh; - int blocks = 0; + int IntraThresh = INTRA_THRESH, + InterThresh = INTER_THRESH + b_thresh, + IntraThresh2 = INTRA_THRESH2; + + int blocks = 10; int complexity = 0; - int32_t iMinSAD[5], temp[5]; - uint32_t dir; - VECTOR currentMV[5]; SearchData Data; Data.iEdgedWidth = pParam->edged_width; - Data.currentMV = currentMV; - Data.iMinSAD = iMinSAD; Data.iFcode = Current->fcode; - Data.temp = temp; - Data.dir = &dir; Data.qpel = (pParam->vol_flags & XVID_VOL_QUARTERPEL)? 1: 0; Data.qpel_precision = 0; if (intraCount != 0) { - if (intraCount < 10) // we're right after an I frame - IntraThresh += 15* (intraCount - 10) * (intraCount - 10); - else - if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec - IntraThresh -= (IntraThresh * (maxIntra - 8*(maxIntra - intraCount)))/maxIntra; + if (intraCount < 30) { + /* we're right after an I frame + we increase thresholds to prevent consecutive i-frames */ + if (intraCount < 10) IntraThresh += 15*(10 - intraCount)*(10 - intraCount); + IntraThresh2 += 4*(30 - intraCount); + } else if (I_SENS_TH*(maxIntra - intraCount) < maxIntra) { + /* we're close to maximum. we decrease thresholds to catch any good keyframe */ + IntraThresh -= IntraThresh*((maxIntra - I_SENS_TH*(maxIntra - intraCount))/maxIntra); + IntraThresh2 -= IntraThresh2*((maxIntra - I_SENS_TH*(maxIntra - intraCount))/maxIntra); + } } - InterThresh -= 20 * bCount; - if (InterThresh < 10 + b_thresh) InterThresh = 10 + b_thresh; + InterThresh -= P_SENS_BIAS * bCount; + if (InterThresh < INTER_THRESH_MIN) InterThresh = INTER_THRESH_MIN; if (sadInit) (*sadInit) (); @@ -182,11 +193,11 @@ blocks += 10; if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV; - else { //extrapolation of the vector found for last frame + else { /* extrapolation of the vector found for last frame */ pMBs[x + y * pParam->mb_width].mvs[0].x = - (pMBs[x + y * pParam->mb_width].mvs[0].x * (bCount+1) ) / bCount; + (prev_mbs[x + y * pParam->mb_width].mvs[0].x * (bCount+1) ) / bCount; pMBs[x + y * pParam->mb_width].mvs[0].y = - (pMBs[x + y * pParam->mb_width].mvs[0].y * (bCount+1) ) / bCount; + (prev_mbs[x + y * pParam->mb_width].mvs[0].y * (bCount+1) ) / bCount; } MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data); @@ -205,9 +216,9 @@ if (pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0) if (dev > 1000 && pMB->sad16 < 1000) - sSAD += 1000; + sSAD += 512; - sSAD += (dev < 4000) ? pMB->sad16 : pMB->sad16/2; /* blocks with big contrast differences usually have large SAD - while they look very good in b-frames */ + sSAD += (dev < 3000) ? pMB->sad16 : pMB->sad16/2; /* blocks with big contrast differences usually have large SAD - while they look very good in b-frames */ } } } @@ -215,8 +226,8 @@ sSAD /= complexity + 4*blocks; - if (intraCount > 80 && sSAD > INTRA_THRESH2 ) return I_VOP; - if (sSAD > InterThresh ) return P_VOP; + if (sSAD > IntraThresh2) return I_VOP; + if (sSAD > InterThresh) return P_VOP; emms(); return B_VOP; }