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