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