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