33 |
#include "motion_inlines.h" |
#include "motion_inlines.h" |
34 |
|
|
35 |
|
|
36 |
#define INTRA_THRESH 2200 |
#define INTRA_THRESH 2000 |
37 |
#define INTER_THRESH 40 |
#define INTER_THRESH 40 |
38 |
#define INTRA_THRESH2 95 |
#define INTRA_THRESH2 90 |
39 |
|
|
40 |
|
/* when we are in 1/I_SENS_TH before forced keyframe, we start to decrese i-frame threshold */ |
41 |
|
#define I_SENS_TH 3 |
42 |
|
|
43 |
|
/* how much we subtract from each p-frame threshold for 2nd, 3rd etc. b-frame in a row */ |
44 |
|
#define P_SENS_BIAS 18 |
45 |
|
|
46 |
|
/* .. but never below INTER_THRESH_MIN */ |
47 |
|
#define INTER_THRESH_MIN 5 |
48 |
|
|
49 |
static void |
static void |
50 |
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) |
51 |
{ |
{ |
52 |
/* maximum speed */ |
/* maximum speed */ |
53 |
int32_t sad; |
int32_t sad; |
61 |
if (sad < *(data->iMinSAD)) { |
if (sad < *(data->iMinSAD)) { |
62 |
*(data->iMinSAD) = sad; |
*(data->iMinSAD) = sad; |
63 |
data->currentMV[0].x = x; data->currentMV[0].y = y; |
data->currentMV[0].x = x; data->currentMV[0].y = y; |
64 |
*data->dir = Direction; |
data->dir = Direction; |
65 |
} |
} |
66 |
if (data->temp[0] < data->iMinSAD[1]) { |
if (data->temp[0] < data->iMinSAD[1]) { |
67 |
data->iMinSAD[1] = data->temp[0]; data->currentMV[1].x = x; data->currentMV[1].y = y; } |
data->iMinSAD[1] = data->temp[0]; data->currentMV[1].x = x; data->currentMV[1].y = y; } |
124 |
CheckCandidate32I(pmv[2].x, pmv[2].y, Data, 2); |
CheckCandidate32I(pmv[2].x, pmv[2].y, Data, 2); |
125 |
|
|
126 |
if (*Data->iMinSAD > 500) { /* diamond only if needed */ |
if (*Data->iMinSAD > 500) { /* diamond only if needed */ |
127 |
unsigned int mask = make_mask(pmv, 3, *Data->dir); |
unsigned int mask = make_mask(pmv, 3, Data->dir); |
128 |
xvid_me_DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, mask, CheckCandidate32I); |
xvid_me_DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, mask, CheckCandidate32I); |
129 |
} else simplicity++; |
} else simplicity++; |
130 |
|
|
146 |
MEanalysis( const IMAGE * const pRef, |
MEanalysis( const IMAGE * const pRef, |
147 |
const FRAMEINFO * const Current, |
const FRAMEINFO * const Current, |
148 |
const MBParam * const pParam, |
const MBParam * const pParam, |
149 |
const int maxIntra, //maximum number if non-I frames |
const int maxIntra, /* maximum number if non-I frames */ |
150 |
const int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame |
const int intraCount, /* number of non-I frames after last I frame; 0 if we force P/B frame */ |
151 |
const int bCount, // number of B frames in a row |
const int bCount, /* number of B frames in a row */ |
152 |
const int b_thresh) |
const int b_thresh, |
153 |
|
const MACROBLOCK * const prev_mbs) |
154 |
{ |
{ |
155 |
uint32_t x, y, intra = 0; |
uint32_t x, y, intra = 0; |
156 |
int sSAD = 0; |
int sSAD = 0; |
157 |
MACROBLOCK * const pMBs = Current->mbs; |
MACROBLOCK * const pMBs = Current->mbs; |
158 |
const IMAGE * const pCurrent = &Current->image; |
const IMAGE * const pCurrent = &Current->image; |
159 |
int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH + b_thresh; |
int IntraThresh = INTRA_THRESH, |
160 |
int blocks = 0; |
InterThresh = INTER_THRESH + b_thresh, |
161 |
|
IntraThresh2 = INTRA_THRESH2; |
162 |
|
|
163 |
|
int blocks = 10; |
164 |
int complexity = 0; |
int complexity = 0; |
165 |
|
|
|
int32_t iMinSAD[5], temp[5]; |
|
|
uint32_t dir; |
|
|
VECTOR currentMV[5]; |
|
166 |
SearchData Data; |
SearchData Data; |
167 |
Data.iEdgedWidth = pParam->edged_width; |
Data.iEdgedWidth = pParam->edged_width; |
|
Data.currentMV = currentMV; |
|
|
Data.iMinSAD = iMinSAD; |
|
168 |
Data.iFcode = Current->fcode; |
Data.iFcode = Current->fcode; |
|
Data.temp = temp; |
|
|
Data.dir = &dir; |
|
169 |
Data.qpel = (pParam->vol_flags & XVID_VOL_QUARTERPEL)? 1: 0; |
Data.qpel = (pParam->vol_flags & XVID_VOL_QUARTERPEL)? 1: 0; |
170 |
Data.qpel_precision = 0; |
Data.qpel_precision = 0; |
171 |
|
|
172 |
if (intraCount != 0) { |
if (intraCount != 0) { |
173 |
if (intraCount < 10) // we're right after an I frame |
if (intraCount < 30) { |
174 |
IntraThresh += 15* (intraCount - 10) * (intraCount - 10); |
/* we're right after an I frame |
175 |
else |
we increase thresholds to prevent consecutive i-frames */ |
176 |
if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec |
if (intraCount < 10) IntraThresh += 15*(10 - intraCount)*(10 - intraCount); |
177 |
IntraThresh -= (IntraThresh * (maxIntra - 8*(maxIntra - intraCount)))/maxIntra; |
IntraThresh2 += 4*(30 - intraCount); |
178 |
|
} else if (I_SENS_TH*(maxIntra - intraCount) < maxIntra) { |
179 |
|
/* we're close to maximum. we decrease thresholds to catch any good keyframe */ |
180 |
|
IntraThresh -= IntraThresh*((maxIntra - I_SENS_TH*(maxIntra - intraCount))/maxIntra); |
181 |
|
IntraThresh2 -= IntraThresh2*((maxIntra - I_SENS_TH*(maxIntra - intraCount))/maxIntra); |
182 |
|
} |
183 |
} |
} |
184 |
|
|
185 |
InterThresh -= 20 * bCount; |
InterThresh -= P_SENS_BIAS * bCount; |
186 |
if (InterThresh < 10 + b_thresh) InterThresh = 10 + b_thresh; |
if (InterThresh < INTER_THRESH_MIN) InterThresh = INTER_THRESH_MIN; |
187 |
|
|
188 |
if (sadInit) (*sadInit) (); |
if (sadInit) (*sadInit) (); |
189 |
|
|
193 |
blocks += 10; |
blocks += 10; |
194 |
|
|
195 |
if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV; |
if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV; |
196 |
else { //extrapolation of the vector found for last frame |
else { /* extrapolation of the vector found for last frame */ |
197 |
pMBs[x + y * pParam->mb_width].mvs[0].x = |
pMBs[x + y * pParam->mb_width].mvs[0].x = |
198 |
(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; |
199 |
pMBs[x + y * pParam->mb_width].mvs[0].y = |
pMBs[x + y * pParam->mb_width].mvs[0].y = |
200 |
(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; |
201 |
} |
} |
202 |
|
|
203 |
MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data); |
MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data); |
216 |
|
|
217 |
if (pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0) |
if (pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0) |
218 |
if (dev > 1000 && pMB->sad16 < 1000) |
if (dev > 1000 && pMB->sad16 < 1000) |
219 |
sSAD += 1000; |
sSAD += 512; |
220 |
|
|
221 |
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 */ |
222 |
} |
} |
223 |
} |
} |
224 |
} |
} |
226 |
|
|
227 |
sSAD /= complexity + 4*blocks; |
sSAD /= complexity + 4*blocks; |
228 |
|
|
229 |
if (intraCount > 80 && sSAD > INTRA_THRESH2 ) return I_VOP; |
if (sSAD > IntraThresh2) return I_VOP; |
230 |
if (sSAD > InterThresh ) return P_VOP; |
if (sSAD > InterThresh ) return P_VOP; |
231 |
emms(); |
emms(); |
232 |
return B_VOP; |
return B_VOP; |