Parent Directory | Revision Log
Revision 1.6 - (view) (download)
1 : | syskin | 1.1 | |
2 : | #include <assert.h> | ||
3 : | #include <stdio.h> | ||
4 : | #include <stdlib.h> | ||
5 : | #include <string.h> /* memcpy */ | ||
6 : | |||
7 : | #include "../encoder.h" | ||
8 : | #include "../bitstream/mbcoding.h" | ||
9 : | #include "../prediction/mbprediction.h" | ||
10 : | #include "../global.h" | ||
11 : | #include "../image/interpolate8x8.h" | ||
12 : | #include "estimation.h" | ||
13 : | #include "motion.h" | ||
14 : | #include "sad.h" | ||
15 : | #include "../bitstream/zigzag.h" | ||
16 : | #include "../quant/quant.h" | ||
17 : | #include "../bitstream/vlc_codes.h" | ||
18 : | #include "../dct/fdct.h" | ||
19 : | #include "motion_inlines.h" | ||
20 : | |||
21 : | /* rd = BITS_MULT*bits + LAMBDA*distortion */ | ||
22 : | #define LAMBDA ( (int)(BITS_MULT*1.0) ) | ||
23 : | |||
24 : | |||
25 : | static __inline unsigned int | ||
26 : | Block_CalcBits_BVOP(int16_t * const coeff, | ||
27 : | int16_t * const data, | ||
28 : | int16_t * const dqcoeff, | ||
29 : | const uint32_t quant, const int quant_type, | ||
30 : | uint32_t * cbp, | ||
31 : | const int block, | ||
32 : | const uint16_t * scan_table, | ||
33 : | const unsigned int lambda, | ||
34 : | syskin | 1.6 | const uint16_t * mpeg_quant_matrices, |
35 : | const unsigned int quant_sq) | ||
36 : | syskin | 1.1 | { |
37 : | int sum; | ||
38 : | int bits; | ||
39 : | int distortion = 0; | ||
40 : | |||
41 : | fdct(data); | ||
42 : | |||
43 : | if (quant_type) sum = quant_h263_inter(coeff, data, quant, mpeg_quant_matrices); | ||
44 : | else sum = quant_mpeg_inter(coeff, data, quant, mpeg_quant_matrices); | ||
45 : | |||
46 : | if ((sum >= 3) || (coeff[1] != 0) || (coeff[8] != 0) || (coeff[0] != 0)) { | ||
47 : | *cbp |= 1 << (5 - block); | ||
48 : | bits = BITS_MULT * CodeCoeffInter_CalcBits(coeff, scan_table); | ||
49 : | |||
50 : | if (quant_type) dequant_h263_inter(dqcoeff, coeff, quant, mpeg_quant_matrices); | ||
51 : | else dequant_mpeg_inter(dqcoeff, coeff, quant, mpeg_quant_matrices); | ||
52 : | |||
53 : | distortion = sse8_16bit(data, dqcoeff, 8*sizeof(int16_t)); | ||
54 : | } else { | ||
55 : | const static int16_t zero_block[64] = | ||
56 : | { | ||
57 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
58 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
59 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
60 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
61 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
62 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
63 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
64 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
65 : | }; | ||
66 : | bits = 0; | ||
67 : | distortion = sse8_16bit(data, zero_block, 8*sizeof(int16_t)); | ||
68 : | } | ||
69 : | |||
70 : | syskin | 1.6 | return bits + (lambda*distortion)/quant_sq; |
71 : | syskin | 1.1 | } |
72 : | |||
73 : | |||
74 : | static __inline unsigned int | ||
75 : | Block_CalcBits_BVOP_direct(int16_t * const coeff, | ||
76 : | int16_t * const data, | ||
77 : | int16_t * const dqcoeff, | ||
78 : | const uint32_t quant, const int quant_type, | ||
79 : | uint32_t * cbp, | ||
80 : | const int block, | ||
81 : | const uint16_t * scan_table, | ||
82 : | const unsigned int lambda, | ||
83 : | syskin | 1.6 | const uint16_t * mpeg_quant_matrices, |
84 : | const unsigned int quant_sq) | ||
85 : | syskin | 1.1 | { |
86 : | int sum; | ||
87 : | int bits; | ||
88 : | int distortion = 0; | ||
89 : | |||
90 : | fdct(data); | ||
91 : | |||
92 : | if (quant_type) sum = quant_h263_inter(coeff, data, quant, mpeg_quant_matrices); | ||
93 : | else sum = quant_mpeg_inter(coeff, data, quant, mpeg_quant_matrices); | ||
94 : | |||
95 : | if ((sum >= 3) || (coeff[1] != 0) || (coeff[8] != 0) || (coeff[0] > 0) || (coeff[0] < -1)) { | ||
96 : | *cbp |= 1 << (5 - block); | ||
97 : | bits = BITS_MULT * CodeCoeffInter_CalcBits(coeff, scan_table); | ||
98 : | |||
99 : | if (quant_type) dequant_h263_inter(dqcoeff, coeff, quant, mpeg_quant_matrices); | ||
100 : | else dequant_mpeg_inter(dqcoeff, coeff, quant, mpeg_quant_matrices); | ||
101 : | |||
102 : | distortion = sse8_16bit(data, dqcoeff, 8*sizeof(int16_t)); | ||
103 : | } else { | ||
104 : | const static int16_t zero_block[64] = | ||
105 : | { | ||
106 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
107 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
108 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
109 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
110 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
111 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
112 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
113 : | 0, 0, 0, 0, 0, 0, 0, 0, | ||
114 : | }; | ||
115 : | bits = 0; | ||
116 : | distortion = sse8_16bit(data, zero_block, 8*sizeof(int16_t)); | ||
117 : | } | ||
118 : | |||
119 : | syskin | 1.6 | return bits + (lambda*distortion)/quant_sq; |
120 : | syskin | 1.1 | } |
121 : | |||
122 : | static void | ||
123 : | CheckCandidateRDBF(const int x, const int y, SearchData * const data, const unsigned int Direction) | ||
124 : | { | ||
125 : | |||
126 : | int16_t *in = data->dctSpace, *coeff = data->dctSpace + 64; | ||
127 : | syskin | 1.6 | int32_t rd = (3+2)*BITS_MULT; /* 3 bits for mode + 2 for vector (minimum) */ |
128 : | syskin | 1.1 | VECTOR * current; |
129 : | const uint8_t * ptr; | ||
130 : | int i, xc, yc; | ||
131 : | unsigned cbp = 0; | ||
132 : | |||
133 : | if ( (x > data->max_dx) || (x < data->min_dx) | ||
134 : | || (y > data->max_dy) || (y < data->min_dy) ) return; | ||
135 : | |||
136 : | if (!data->qpel_precision) { | ||
137 : | ptr = GetReference(x, y, data); | ||
138 : | current = data->currentMV; | ||
139 : | xc = x; yc = y; | ||
140 : | } else { /* x and y are in 1/4 precision */ | ||
141 : | ptr = xvid_me_interpolate16x16qpel(x, y, 0, data); | ||
142 : | current = data->currentQMV; | ||
143 : | xc = x/2; yc = y/2; | ||
144 : | } | ||
145 : | |||
146 : | syskin | 1.6 | rd += BITS_MULT*(d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision)-2); |
147 : | syskin | 1.1 | |
148 : | for(i = 0; i < 4; i++) { | ||
149 : | int s = 8*((i&1) + (i>>1)*data->iEdgedWidth); | ||
150 : | transfer_8to16subro(in, data->Cur + s, ptr + s, data->iEdgedWidth); | ||
151 : | syskin | 1.6 | rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, |
152 : | &cbp, i, data->scan_table, data->lambda[i], data->mpeg_quant_matrices, data->quant_sq); | ||
153 : | syskin | 1.1 | if (rd >= data->iMinSAD[0]) return; |
154 : | } | ||
155 : | |||
156 : | /* chroma */ | ||
157 : | xc = (xc >> 1) + roundtab_79[xc & 0x3]; | ||
158 : | yc = (yc >> 1) + roundtab_79[yc & 0x3]; | ||
159 : | |||
160 : | /* chroma U */ | ||
161 : | ptr = interpolate8x8_switch2(data->RefQ, data->RefP[4], 0, 0, xc, yc, data->iEdgedWidth/2, data->rounding); | ||
162 : | transfer_8to16subro(in, data->CurU, ptr, data->iEdgedWidth/2); | ||
163 : | syskin | 1.6 | rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, |
164 : | &cbp, 4, data->scan_table, data->lambda[4], data->mpeg_quant_matrices, data->quant_sq); | ||
165 : | syskin | 1.1 | if (rd >= data->iMinSAD[0]) return; |
166 : | |||
167 : | /* chroma V */ | ||
168 : | ptr = interpolate8x8_switch2(data->RefQ, data->RefP[5], 0, 0, xc, yc, data->iEdgedWidth/2, data->rounding); | ||
169 : | transfer_8to16subro(in, data->CurV, ptr, data->iEdgedWidth/2); | ||
170 : | syskin | 1.6 | rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, |
171 : | &cbp, 5, data->scan_table, data->lambda[5], data->mpeg_quant_matrices, data->quant_sq); | ||
172 : | syskin | 1.1 | |
173 : | if (cbp) rd += BITS_MULT * 7; | ||
174 : | |||
175 : | if (rd < data->iMinSAD[0]) { | ||
176 : | data->iMinSAD[0] = rd; | ||
177 : | current[0].x = x; current[0].y = y; | ||
178 : | data->dir = Direction; | ||
179 : | *data->cbp = cbp; | ||
180 : | } | ||
181 : | } | ||
182 : | |||
183 : | static void | ||
184 : | CheckCandidateRDDirect(const int x, const int y, SearchData * const data, const unsigned int Direction) | ||
185 : | { | ||
186 : | int32_t xcf = 0, ycf = 0, xcb = 0, ycb = 0; | ||
187 : | int32_t rd = 1*BITS_MULT; | ||
188 : | int16_t *in = data->dctSpace, *coeff = data->dctSpace + 64; | ||
189 : | unsigned int cbp = 0; | ||
190 : | unsigned int k; | ||
191 : | VECTOR mvs, b_mvs; | ||
192 : | |||
193 : | const uint8_t *ReferenceF, *ReferenceB; | ||
194 : | |||
195 : | if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return; | ||
196 : | |||
197 : | for (k = 0; k < 4; k++) { | ||
198 : | int s = 8*((k&1) + (k>>1)*data->iEdgedWidth); | ||
199 : | |||
200 : | mvs.x = data->directmvF[k].x + x; | ||
201 : | b_mvs.x = ((x == 0) ? | ||
202 : | data->directmvB[k].x | ||
203 : | : mvs.x - data->referencemv[k].x); | ||
204 : | |||
205 : | mvs.y = data->directmvF[k].y + y; | ||
206 : | b_mvs.y = ((y == 0) ? | ||
207 : | data->directmvB[k].y | ||
208 : | : mvs.y - data->referencemv[k].y); | ||
209 : | |||
210 : | if ((mvs.x > data->max_dx) || (mvs.x < data->min_dx) || | ||
211 : | (mvs.y > data->max_dy) || (mvs.y < data->min_dy) || | ||
212 : | (b_mvs.x > data->max_dx) || (b_mvs.x < data->min_dx) || | ||
213 : | (b_mvs.y > data->max_dy) || (b_mvs.y < data->min_dy) ) | ||
214 : | return; | ||
215 : | |||
216 : | if (data->qpel) { | ||
217 : | xcf += mvs.x/2; ycf += mvs.y/2; | ||
218 : | xcb += b_mvs.x/2; ycb += b_mvs.y/2; | ||
219 : | ReferenceF = xvid_me_interpolate8x8qpel(mvs.x, mvs.y, k, 0, data); | ||
220 : | ReferenceB = xvid_me_interpolate8x8qpel(b_mvs.x, b_mvs.y, k, 1, data); | ||
221 : | } else { | ||
222 : | xcf += mvs.x; ycf += mvs.y; | ||
223 : | xcb += b_mvs.x; ycb += b_mvs.y; | ||
224 : | ReferenceF = GetReference(mvs.x, mvs.y, data) + s; | ||
225 : | ReferenceB = GetReferenceB(b_mvs.x, b_mvs.y, 1, data) + s; | ||
226 : | } | ||
227 : | |||
228 : | transfer_8to16sub2ro(in, data->Cur + s, ReferenceF, ReferenceB, data->iEdgedWidth); | ||
229 : | syskin | 1.6 | rd += Block_CalcBits_BVOP_direct(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, |
230 : | &cbp, k, data->scan_table, data->lambda[k], data->mpeg_quant_matrices, data->quant_sq); | ||
231 : | syskin | 1.1 | if (rd > *(data->iMinSAD)) return; |
232 : | } | ||
233 : | |||
234 : | /* chroma */ | ||
235 : | xcf = (xcf >> 3) + roundtab_76[xcf & 0xf]; | ||
236 : | ycf = (ycf >> 3) + roundtab_76[ycf & 0xf]; | ||
237 : | xcb = (xcb >> 3) + roundtab_76[xcb & 0xf]; | ||
238 : | ycb = (ycb >> 3) + roundtab_76[ycb & 0xf]; | ||
239 : | |||
240 : | /* chroma U */ | ||
241 : | ReferenceF = interpolate8x8_switch2(data->RefQ, data->RefP[4], 0, 0, xcf, ycf, data->iEdgedWidth/2, data->rounding); | ||
242 : | ReferenceB = interpolate8x8_switch2(data->RefQ + 16, data->b_RefP[4], 0, 0, xcb, ycb, data->iEdgedWidth/2, data->rounding); | ||
243 : | transfer_8to16sub2ro(in, data->CurU, ReferenceF, ReferenceB, data->iEdgedWidth/2); | ||
244 : | syskin | 1.6 | rd += Block_CalcBits_BVOP_direct(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, |
245 : | &cbp, 4, data->scan_table, data->lambda[4], data->mpeg_quant_matrices, data->quant_sq); | ||
246 : | syskin | 1.1 | if (rd >= data->iMinSAD[0]) return; |
247 : | |||
248 : | /* chroma V */ | ||
249 : | ReferenceF = interpolate8x8_switch2(data->RefQ, data->RefP[5], 0, 0, xcf, ycf, data->iEdgedWidth/2, data->rounding); | ||
250 : | ReferenceB = interpolate8x8_switch2(data->RefQ + 16, data->b_RefP[5], 0, 0, xcb, ycb, data->iEdgedWidth/2, data->rounding); | ||
251 : | transfer_8to16sub2ro(in, data->CurV, ReferenceF, ReferenceB, data->iEdgedWidth/2); | ||
252 : | syskin | 1.6 | rd += Block_CalcBits_BVOP_direct(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, |
253 : | &cbp, 5, data->scan_table, data->lambda[5], data->mpeg_quant_matrices, data->quant_sq); | ||
254 : | syskin | 1.1 | |
255 : | if (cbp) | ||
256 : | rd += BITS_MULT * 6; | ||
257 : | if (cbp || x != 0 || y != 0) | ||
258 : | syskin | 1.4 | rd += BITS_MULT * d_mv_bits(x, y, zeroMV, 1, 0); |
259 : | syskin | 1.1 | |
260 : | if (rd < *(data->iMinSAD)) { | ||
261 : | *data->iMinSAD = rd; | ||
262 : | data->currentMV->x = x; data->currentMV->y = y; | ||
263 : | data->dir = Direction; | ||
264 : | *data->cbp = cbp; | ||
265 : | } | ||
266 : | } | ||
267 : | |||
268 : | static void | ||
269 : | CheckCandidateRDInt(const int x, const int y, SearchData * const data, const unsigned int Direction) | ||
270 : | { | ||
271 : | int32_t xf, yf, xb, yb, xcf, ycf, xcb, ycb; | ||
272 : | int32_t rd = 2*BITS_MULT; | ||
273 : | int16_t *in = data->dctSpace, *coeff = data->dctSpace + 64; | ||
274 : | unsigned int cbp = 0; | ||
275 : | unsigned int i; | ||
276 : | |||
277 : | const uint8_t *ReferenceF, *ReferenceB; | ||
278 : | VECTOR *current; | ||
279 : | |||
280 : | if ((x > data->max_dx) || (x < data->min_dx) || | ||
281 : | (y > data->max_dy) || (y < data->min_dy)) | ||
282 : | return; | ||
283 : | |||
284 : | if (Direction == 1) { /* x and y mean forward vector */ | ||
285 : | VECTOR backward = data->qpel_precision ? data->currentQMV[1] : data->currentMV[1]; | ||
286 : | xb = backward.x; | ||
287 : | yb = backward.y; | ||
288 : | xf = x; yf = y; | ||
289 : | } else { /* x and y mean backward vector */ | ||
290 : | VECTOR forward = data->qpel_precision ? data->currentQMV[0] : data->currentMV[0]; | ||
291 : | xf = forward.x; | ||
292 : | yf = forward.y; | ||
293 : | xb = x; yb = y; | ||
294 : | } | ||
295 : | |||
296 : | if (!data->qpel_precision) { | ||
297 : | ReferenceF = GetReference(xf, yf, data); | ||
298 : | ReferenceB = GetReferenceB(xb, yb, 1, data); | ||
299 : | current = data->currentMV + Direction - 1; | ||
300 : | xcf = xf; ycf = yf; | ||
301 : | xcb = xb; ycb = yb; | ||
302 : | } else { | ||
303 : | ReferenceF = xvid_me_interpolate16x16qpel(xf, yf, 0, data); | ||
304 : | current = data->currentQMV + Direction - 1; | ||
305 : | ReferenceB = xvid_me_interpolate16x16qpel(xb, yb, 1, data); | ||
306 : | xcf = xf/2; ycf = yf/2; | ||
307 : | xcb = xb/2; ycb = yb/2; | ||
308 : | } | ||
309 : | |||
310 : | syskin | 1.4 | rd += BITS_MULT * (d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel^data->qpel_precision) |
311 : | + d_mv_bits(xb, yb, data->bpredMV, data->iFcode, data->qpel^data->qpel_precision)); | ||
312 : | syskin | 1.1 | |
313 : | for(i = 0; i < 4; i++) { | ||
314 : | int s = 8*((i&1) + (i>>1)*data->iEdgedWidth); | ||
315 : | if (rd >= *data->iMinSAD) return; | ||
316 : | transfer_8to16sub2ro(in, data->Cur + s, ReferenceF + s, ReferenceB + s, data->iEdgedWidth); | ||
317 : | syskin | 1.6 | rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, |
318 : | i, data->scan_table, data->lambda[i], data->mpeg_quant_matrices, data->quant_sq); | ||
319 : | syskin | 1.1 | } |
320 : | |||
321 : | /* chroma */ | ||
322 : | xcf = (xcf >> 1) + roundtab_79[xcf & 0x3]; | ||
323 : | ycf = (ycf >> 1) + roundtab_79[ycf & 0x3]; | ||
324 : | xcb = (xcb >> 1) + roundtab_79[xcb & 0x3]; | ||
325 : | ycb = (ycb >> 1) + roundtab_79[ycb & 0x3]; | ||
326 : | |||
327 : | /* chroma U */ | ||
328 : | ReferenceF = interpolate8x8_switch2(data->RefQ, data->RefP[4], 0, 0, xcf, ycf, data->iEdgedWidth/2, data->rounding); | ||
329 : | ReferenceB = interpolate8x8_switch2(data->RefQ + 16, data->b_RefP[4], 0, 0, xcb, ycb, data->iEdgedWidth/2, data->rounding); | ||
330 : | transfer_8to16sub2ro(in, data->CurU, ReferenceF, ReferenceB, data->iEdgedWidth/2); | ||
331 : | syskin | 1.6 | rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, |
332 : | 4, data->scan_table, data->lambda[4], data->mpeg_quant_matrices, data->quant_sq); | ||
333 : | syskin | 1.1 | if (rd >= data->iMinSAD[0]) return; |
334 : | |||
335 : | |||
336 : | /* chroma V */ | ||
337 : | ReferenceF = interpolate8x8_switch2(data->RefQ, data->RefP[5], 0, 0, xcf, ycf, data->iEdgedWidth/2, data->rounding); | ||
338 : | ReferenceB = interpolate8x8_switch2(data->RefQ + 16, data->b_RefP[5], 0, 0, xcb, ycb, data->iEdgedWidth/2, data->rounding); | ||
339 : | transfer_8to16sub2ro(in, data->CurV, ReferenceF, ReferenceB, data->iEdgedWidth/2); | ||
340 : | syskin | 1.6 | rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp, |
341 : | 5, data->scan_table, data->lambda[5], data->mpeg_quant_matrices, data->quant_sq); | ||
342 : | syskin | 1.1 | |
343 : | if (cbp) rd += BITS_MULT * 7; | ||
344 : | |||
345 : | if (rd < *(data->iMinSAD)) { | ||
346 : | *data->iMinSAD = rd; | ||
347 : | current->x = x; current->y = y; | ||
348 : | data->dir = Direction; | ||
349 : | *data->cbp = cbp; | ||
350 : | } | ||
351 : | } | ||
352 : | |||
353 : | static int | ||
354 : | SearchInterpolate_RD(const int x, const int y, | ||
355 : | const uint32_t MotionFlags, | ||
356 : | const MBParam * const pParam, | ||
357 : | int32_t * const best_sad, | ||
358 : | SearchData * const Data) | ||
359 : | { | ||
360 : | int i, j; | ||
361 : | |||
362 : | Data->iMinSAD[0] = *best_sad; | ||
363 : | |||
364 : | get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, | ||
365 : | syskin | 1.4 | x, y, 4, pParam->width, pParam->height, Data->iFcode, 1 + Data->qpel); |
366 : | syskin | 1.1 | |
367 : | Data->qpel_precision = Data->qpel; | ||
368 : | |||
369 : | if (Data->qpel) { | ||
370 : | i = Data->currentQMV[0].x; j = Data->currentQMV[0].y; | ||
371 : | } else { | ||
372 : | i = Data->currentMV[0].x; j = Data->currentMV[0].y; | ||
373 : | } | ||
374 : | |||
375 : | CheckCandidateRDInt(i, j, Data, 1); | ||
376 : | |||
377 : | return Data->iMinSAD[0]; | ||
378 : | } | ||
379 : | |||
380 : | static int | ||
381 : | SearchDirect_RD(const int x, const int y, | ||
382 : | const uint32_t MotionFlags, | ||
383 : | const MBParam * const pParam, | ||
384 : | int32_t * const best_sad, | ||
385 : | SearchData * const Data) | ||
386 : | { | ||
387 : | Data->iMinSAD[0] = *best_sad; | ||
388 : | |||
389 : | Data->qpel_precision = Data->qpel; | ||
390 : | |||
391 : | CheckCandidateRDDirect(Data->currentMV->x, Data->currentMV->y, Data, 255); | ||
392 : | |||
393 : | return Data->iMinSAD[0]; | ||
394 : | } | ||
395 : | |||
396 : | static int | ||
397 : | SearchBF_RD(const int x, const int y, | ||
398 : | const uint32_t MotionFlags, | ||
399 : | const MBParam * const pParam, | ||
400 : | int32_t * const best_sad, | ||
401 : | SearchData * const Data) | ||
402 : | { | ||
403 : | int i, j; | ||
404 : | |||
405 : | Data->iMinSAD[0] = *best_sad; | ||
406 : | |||
407 : | get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, | ||
408 : | syskin | 1.4 | x, y, 4, pParam->width, pParam->height, Data->iFcode, 1 + Data->qpel); |
409 : | syskin | 1.1 | |
410 : | Data->qpel_precision = Data->qpel; | ||
411 : | |||
412 : | if (Data->qpel) { | ||
413 : | i = Data->currentQMV[0].x; j = Data->currentQMV[0].y; | ||
414 : | } else { | ||
415 : | i = Data->currentMV[0].x; j = Data->currentMV[0].y; | ||
416 : | } | ||
417 : | |||
418 : | CheckCandidateRDBF(i, j, Data, 1); | ||
419 : | |||
420 : | return Data->iMinSAD[0]; | ||
421 : | } | ||
422 : | |||
423 : | static int | ||
424 : | get_sad_for_mode(int mode, | ||
425 : | SearchData * const Data_d, | ||
426 : | SearchData * const Data_b, | ||
427 : | SearchData * const Data_f, | ||
428 : | SearchData * const Data_i) | ||
429 : | { | ||
430 : | switch(mode) { | ||
431 : | case MODE_DIRECT: return Data_d->iMinSAD[0]; | ||
432 : | case MODE_FORWARD: return Data_f->iMinSAD[0]; | ||
433 : | case MODE_BACKWARD: return Data_b->iMinSAD[0]; | ||
434 : | default: | ||
435 : | case MODE_INTERPOLATE: return Data_i->iMinSAD[0]; | ||
436 : | } | ||
437 : | } | ||
438 : | |||
439 : | void | ||
440 : | ModeDecision_BVOP_RD(SearchData * const Data_d, | ||
441 : | SearchData * const Data_b, | ||
442 : | SearchData * const Data_f, | ||
443 : | SearchData * const Data_i, | ||
444 : | MACROBLOCK * const pMB, | ||
445 : | const MACROBLOCK * const b_mb, | ||
446 : | VECTOR * f_predMV, | ||
447 : | VECTOR * b_predMV, | ||
448 : | const uint32_t MotionFlags, | ||
449 : | const MBParam * const pParam, | ||
450 : | syskin | 1.5 | int x, int y, |
451 : | int best_sad) | ||
452 : | syskin | 1.1 | { |
453 : | int mode = MODE_DIRECT, k; | ||
454 : | int f_rd, b_rd, i_rd, d_rd, best_rd; | ||
455 : | const int qpel = Data_d->qpel; | ||
456 : | const uint32_t iQuant = Data_d->iQuant; | ||
457 : | int i; | ||
458 : | int ref_quant = b_mb->quant; | ||
459 : | syskin | 1.5 | int no_of_checks = 0; |
460 : | syskin | 1.1 | |
461 : | int order[4] = {MODE_DIRECT, MODE_FORWARD, MODE_BACKWARD, MODE_INTERPOLATE}; | ||
462 : | |||
463 : | Data_d->scan_table = Data_b->scan_table = Data_f->scan_table = Data_i->scan_table | ||
464 : | = /*VopFlags & XVID_VOP_ALTERNATESCAN ? scan_tables[2] : */scan_tables[0]; | ||
465 : | syskin | 1.5 | *Data_f->cbp = *Data_b->cbp = *Data_i->cbp = *Data_d->cbp = 63; |
466 : | syskin | 1.1 | |
467 : | f_rd = b_rd = i_rd = d_rd = best_rd = 256*4096; | ||
468 : | |||
469 : | for (i = 0; i < 6; i++) { | ||
470 : | int lam = (LAMBDA*iQuant*iQuant)/(ref_quant*(ref_quant+1)); /* re-calculate as if it was p-frame's quant +.5 */ | ||
471 : | Data_d->lambda[i] = lam; | ||
472 : | Data_b->lambda[i] = lam; | ||
473 : | Data_f->lambda[i] = lam; | ||
474 : | Data_i->lambda[i] = lam; | ||
475 : | } | ||
476 : | |||
477 : | /* find the best order of evaluation - smallest SAD comes first, because *if* it means smaller RD, | ||
478 : | early-stops will activate sooner */ | ||
479 : | |||
480 : | for (i = 3; i >= 0; i--) { | ||
481 : | int j; | ||
482 : | for (j = 0; j < i; j++) { | ||
483 : | int sad1 = get_sad_for_mode(order[j], Data_d, Data_b, Data_f, Data_i); | ||
484 : | int sad2 = get_sad_for_mode(order[j+1], Data_d, Data_b, Data_f, Data_i); | ||
485 : | if (sad1 > sad2) { | ||
486 : | int t = order[j]; | ||
487 : | order[j] = order[j+1]; | ||
488 : | order[j+1] = t; | ||
489 : | } | ||
490 : | } | ||
491 : | } | ||
492 : | |||
493 : | syskin | 1.5 | for(i = 0; i < 4; i++) |
494 : | if (get_sad_for_mode(order[i], Data_d, Data_b, Data_f, Data_i) < 2*best_sad) | ||
495 : | no_of_checks++; | ||
496 : | |||
497 : | if (no_of_checks > 1) { | ||
498 : | /* evaluate cost of all modes */ | ||
499 : | for (i = 0; i < no_of_checks; i++) { | ||
500 : | int rd; | ||
501 : | if (2*best_sad < get_sad_for_mode(order[i], Data_d, Data_b, Data_f, Data_i)) | ||
502 : | break; /* further SADs are too big */ | ||
503 : | |||
504 : | switch (order[i]) { | ||
505 : | case MODE_DIRECT: | ||
506 : | rd = d_rd = SearchDirect_RD(x, y, MotionFlags, pParam, &best_rd, Data_d); | ||
507 : | break; | ||
508 : | case MODE_FORWARD: | ||
509 : | rd = f_rd = SearchBF_RD(x, y, MotionFlags, pParam, &best_rd, Data_f) + 1*BITS_MULT; /* extra one bit for FORWARD vs BACKWARD */ | ||
510 : | break; | ||
511 : | case MODE_BACKWARD: | ||
512 : | rd = b_rd = SearchBF_RD(x, y, MotionFlags, pParam, &best_rd, Data_b); | ||
513 : | break; | ||
514 : | default: | ||
515 : | case MODE_INTERPOLATE: | ||
516 : | rd = i_rd = SearchInterpolate_RD(x, y, MotionFlags, pParam, &best_rd, Data_i); | ||
517 : | break; | ||
518 : | } | ||
519 : | if (rd < best_rd) { | ||
520 : | mode = order[i]; | ||
521 : | best_rd = rd; | ||
522 : | } | ||
523 : | syskin | 1.1 | } |
524 : | syskin | 1.5 | } else { |
525 : | /* only 1 mode is below the threshold */ | ||
526 : | mode = order[0]; | ||
527 : | best_rd = 0; | ||
528 : | syskin | 1.1 | } |
529 : | |||
530 : | pMB->sad16 = best_rd; | ||
531 : | pMB->mode = mode; | ||
532 : | |||
533 : | switch (mode) { | ||
534 : | |||
535 : | case MODE_DIRECT: | ||
536 : | if (!qpel && b_mb->mode != MODE_INTER4V) pMB->mode = MODE_DIRECT_NO4V; /* for faster compensation */ | ||
537 : | |||
538 : | pMB->pmvs[3] = Data_d->currentMV[0]; | ||
539 : | |||
540 : | pMB->cbp = *Data_d->cbp; | ||
541 : | |||
542 : | for (k = 0; k < 4; k++) { | ||
543 : | pMB->mvs[k].x = Data_d->directmvF[k].x + Data_d->currentMV->x; | ||
544 : | pMB->b_mvs[k].x = ( (Data_d->currentMV->x == 0) | ||
545 : | ? Data_d->directmvB[k].x | ||
546 : | :pMB->mvs[k].x - Data_d->referencemv[k].x); | ||
547 : | pMB->mvs[k].y = (Data_d->directmvF[k].y + Data_d->currentMV->y); | ||
548 : | pMB->b_mvs[k].y = ((Data_d->currentMV->y == 0) | ||
549 : | ? Data_d->directmvB[k].y | ||
550 : | : pMB->mvs[k].y - Data_d->referencemv[k].y); | ||
551 : | if (qpel) { | ||
552 : | pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2; | ||
553 : | pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2; | ||
554 : | pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2; | ||
555 : | pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2; | ||
556 : | } | ||
557 : | |||
558 : | if (b_mb->mode != MODE_INTER4V) { | ||
559 : | pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0]; | ||
560 : | pMB->b_mvs[3] = pMB->b_mvs[2] = pMB->b_mvs[1] = pMB->b_mvs[0]; | ||
561 : | pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0]; | ||
562 : | pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0]; | ||
563 : | break; | ||
564 : | } | ||
565 : | } | ||
566 : | break; | ||
567 : | |||
568 : | case MODE_FORWARD: | ||
569 : | if (qpel) { | ||
570 : | pMB->pmvs[0].x = Data_f->currentQMV->x - f_predMV->x; | ||
571 : | pMB->pmvs[0].y = Data_f->currentQMV->y - f_predMV->y; | ||
572 : | pMB->qmvs[0] = *Data_f->currentQMV; | ||
573 : | *f_predMV = Data_f->currentQMV[0]; | ||
574 : | } else { | ||
575 : | pMB->pmvs[0].x = Data_f->currentMV->x - f_predMV->x; | ||
576 : | pMB->pmvs[0].y = Data_f->currentMV->y - f_predMV->y; | ||
577 : | *f_predMV = Data_f->currentMV[0]; | ||
578 : | } | ||
579 : | pMB->mvs[0] = *Data_f->currentMV; | ||
580 : | pMB->cbp = *Data_f->cbp; | ||
581 : | syskin | 1.3 | pMB->b_mvs[0] = *Data_b->currentMV; /* hint for future searches */ |
582 : | syskin | 1.1 | break; |
583 : | |||
584 : | case MODE_BACKWARD: | ||
585 : | if (qpel) { | ||
586 : | pMB->pmvs[0].x = Data_b->currentQMV->x - b_predMV->x; | ||
587 : | pMB->pmvs[0].y = Data_b->currentQMV->y - b_predMV->y; | ||
588 : | pMB->b_qmvs[0] = *Data_b->currentQMV; | ||
589 : | *b_predMV = Data_b->currentQMV[0]; | ||
590 : | } else { | ||
591 : | pMB->pmvs[0].x = Data_b->currentMV->x - b_predMV->x; | ||
592 : | pMB->pmvs[0].y = Data_b->currentMV->y - b_predMV->y; | ||
593 : | *b_predMV = Data_b->currentMV[0]; | ||
594 : | } | ||
595 : | pMB->b_mvs[0] = *Data_b->currentMV; | ||
596 : | pMB->cbp = *Data_b->cbp; | ||
597 : | syskin | 1.3 | pMB->mvs[0] = *Data_f->currentMV; /* hint for future searches */ |
598 : | syskin | 1.1 | break; |
599 : | |||
600 : | |||
601 : | case MODE_INTERPOLATE: | ||
602 : | pMB->mvs[0] = Data_i->currentMV[0]; | ||
603 : | pMB->b_mvs[0] = Data_i->currentMV[1]; | ||
604 : | if (qpel) { | ||
605 : | pMB->qmvs[0] = Data_i->currentQMV[0]; | ||
606 : | pMB->b_qmvs[0] = Data_i->currentQMV[1]; | ||
607 : | pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x; | ||
608 : | pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y; | ||
609 : | pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x; | ||
610 : | pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y; | ||
611 : | *f_predMV = Data_i->currentQMV[0]; | ||
612 : | *b_predMV = Data_i->currentQMV[1]; | ||
613 : | } else { | ||
614 : | pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x; | ||
615 : | pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y; | ||
616 : | pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x; | ||
617 : | pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y; | ||
618 : | *f_predMV = Data_i->currentMV[0]; | ||
619 : | *b_predMV = Data_i->currentMV[1]; | ||
620 : | } | ||
621 : | pMB->cbp = *Data_i->cbp; | ||
622 : | break; | ||
623 : | } | ||
624 : | } |
No admin address has been configured | ViewVC Help |
Powered by ViewVC 1.0.4 |