[cvs] / xvidcore / src / motion / estimation_common.c Repository:
ViewVC logotype

Annotation of /xvidcore/src/motion/estimation_common.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12.2.1 - (view) (download)

1 : edgomez 1.2 /*****************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC
4 :     * - Motion Estimation shared functions -
5 :     *
6 :     * Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7 :     * 2002 Michael Militzer <michael@xvid.org>
8 :     * 2002-2003 Radoslaw Czyz <xvid@syskin.cjb.net>
9 :     *
10 :     * This program is free software ; you can redistribute it and/or modify
11 :     * it under the terms of the GNU General Public License as published by
12 :     * the Free Software Foundation ; either version 2 of the License, or
13 :     * (at your option) any later version.
14 :     *
15 :     * This program is distributed in the hope that it will be useful,
16 :     * but WITHOUT ANY WARRANTY ; without even the implied warranty of
17 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 :     * GNU General Public License for more details.
19 :     *
20 :     * You should have received a copy of the GNU General Public License
21 :     * along with this program ; if not, write to the Free Software
22 :     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 :     *
24 : syskin 1.12.2.1 * $Id: estimation_common.c,v 1.12 2005/05/23 09:29:43 Skal Exp $
25 : edgomez 1.2 *
26 :     ****************************************************************************/
27 :    
28 :     #include "../encoder.h"
29 :     #include "../global.h"
30 :     #include "../image/interpolate8x8.h"
31 :     #include "estimation.h"
32 :     #include "motion.h"
33 :     #include "sad.h"
34 :     #include "motion_inlines.h"
35 :    
36 :    
37 :     /*****************************************************************************
38 :     * Modified rounding tables
39 :     * Original tables see ISO spec tables 7-6 -> 7-9
40 :     ****************************************************************************/
41 :    
42 :     const uint32_t roundtab[16] =
43 :     {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2 };
44 :    
45 :     /* K = 4 */
46 :     const uint32_t roundtab_76[16] =
47 :     { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };
48 :    
49 :     /* K = 2 */
50 :     const uint32_t roundtab_78[8] =
51 :     { 0, 0, 1, 1, 0, 0, 0, 1 };
52 :    
53 :     /* K = 1 */
54 :     const uint32_t roundtab_79[4] =
55 :     { 0, 1, 0, 0 };
56 :    
57 :     const int xvid_me_lambda_vec16[32] =
58 : syskin 1.12.2.1 { 0 ,(int)(1.0 * NEIGH_TEND_16X16 + 0.5),
59 :     (int)(2.0*NEIGH_TEND_16X16 + 0.5), (int)(3.0*NEIGH_TEND_16X16 + 0.5),
60 :     (int)(4.0*NEIGH_TEND_16X16 + 0.5), (int)(5.0*NEIGH_TEND_16X16 + 0.5),
61 :     (int)(6.0*NEIGH_TEND_16X16 + 0.5), (int)(7.0*NEIGH_TEND_16X16 + 0.5),
62 : Isibaar 1.11 (int)(8.0*NEIGH_TEND_16X16 + 0.5), (int)(9.0*NEIGH_TEND_16X16 + 0.5),
63 :     (int)(10.0*NEIGH_TEND_16X16 + 0.5), (int)(11.0*NEIGH_TEND_16X16 + 0.5),
64 :     (int)(12.0*NEIGH_TEND_16X16 + 0.5), (int)(13.0*NEIGH_TEND_16X16 + 0.5),
65 :     (int)(14.0*NEIGH_TEND_16X16 + 0.5), (int)(15.0*NEIGH_TEND_16X16 + 0.5),
66 :     (int)(16.0*NEIGH_TEND_16X16 + 0.5), (int)(17.0*NEIGH_TEND_16X16 + 0.5),
67 :     (int)(18.0*NEIGH_TEND_16X16 + 0.5), (int)(19.0*NEIGH_TEND_16X16 + 0.5),
68 :     (int)(20.0*NEIGH_TEND_16X16 + 0.5), (int)(21.0*NEIGH_TEND_16X16 + 0.5),
69 :     (int)(22.0*NEIGH_TEND_16X16 + 0.5), (int)(23.0*NEIGH_TEND_16X16 + 0.5),
70 :     (int)(24.0*NEIGH_TEND_16X16 + 0.5), (int)(25.0*NEIGH_TEND_16X16 + 0.5),
71 :     (int)(26.0*NEIGH_TEND_16X16 + 0.5), (int)(27.0*NEIGH_TEND_16X16 + 0.5),
72 :     (int)(28.0*NEIGH_TEND_16X16 + 0.5), (int)(29.0*NEIGH_TEND_16X16 + 0.5),
73 :     (int)(30.0*NEIGH_TEND_16X16 + 0.5), (int)(31.0*NEIGH_TEND_16X16 + 0.5)
74 : edgomez 1.2 };
75 :    
76 :     /*****************************************************************************
77 :     * Code
78 :     ****************************************************************************/
79 :    
80 :     int32_t
81 :     xvid_me_ChromaSAD(const int dx, const int dy, SearchData * const data)
82 :     {
83 :     int sad;
84 :     const uint32_t stride = data->iEdgedWidth/2;
85 :     int offset = (dx>>1) + (dy>>1)*stride;
86 :     int next = 1;
87 :    
88 :     if (dx == data->chromaX && dy == data->chromaY)
89 :     return data->chromaSAD; /* it has been checked recently */
90 :     data->chromaX = dx; data->chromaY = dy; /* backup */
91 :    
92 :     switch (((dx & 1) << 1) | (dy & 1)) {
93 :     case 0:
94 :     sad = sad8(data->CurU, data->RefP[4] + offset, stride);
95 :     sad += sad8(data->CurV, data->RefP[5] + offset, stride);
96 :     break;
97 :     case 1:
98 :     next = stride;
99 :     case 2:
100 :     sad = sad8bi(data->CurU, data->RefP[4] + offset, data->RefP[4] + offset + next, stride);
101 :     sad += sad8bi(data->CurV, data->RefP[5] + offset, data->RefP[5] + offset + next, stride);
102 :     break;
103 :     default:
104 :     interpolate8x8_halfpel_hv(data->RefQ, data->RefP[4] + offset, stride, data->rounding);
105 :     sad = sad8(data->CurU, data->RefQ, stride);
106 :    
107 :     interpolate8x8_halfpel_hv(data->RefQ, data->RefP[5] + offset, stride, data->rounding);
108 :     sad += sad8(data->CurV, data->RefQ, stride);
109 :     break;
110 :     }
111 :     data->chromaSAD = sad; /* backup, part 2 */
112 :     return sad;
113 :     }
114 :    
115 :     uint8_t *
116 :     xvid_me_interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
117 :     {
118 :     /* create or find a qpel-precision reference picture; return pointer to it */
119 :     uint8_t * Reference = data->RefQ + 16*dir;
120 :     const uint32_t iEdgedWidth = data->iEdgedWidth;
121 :     const uint32_t rounding = data->rounding;
122 :     const int halfpel_x = x/2;
123 :     const int halfpel_y = y/2;
124 :     const uint8_t *ref1, *ref2, *ref3, *ref4;
125 :    
126 :     ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
127 :     ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
128 :     switch( ((x&1)<<1) + (y&1) ) {
129 :     case 3: /* x and y in qpel resolution - the "corners" (top left/right and */
130 :     /* bottom left/right) during qpel refinement */
131 :     ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
132 :     ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
133 :     ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
134 :     ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
135 :     ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
136 :     ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
137 :     interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
138 :     break;
139 :    
140 :     case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
141 :     ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
142 :     ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
143 :     interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
144 :     break;
145 :    
146 :     case 2: /* x qpel, y halfpel - left or right during qpel refinement */
147 :     ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
148 :     ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
149 :     interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
150 :     break;
151 :    
152 :     default: /* pure halfpel position */
153 :     return (uint8_t *) ref1;
154 :    
155 :     }
156 :     return Reference;
157 :     }
158 :    
159 :     uint8_t *
160 :     xvid_me_interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
161 :     {
162 :     /* create or find a qpel-precision reference picture; return pointer to it */
163 :     uint8_t * Reference = data->RefQ + 16*dir;
164 :     const uint32_t iEdgedWidth = data->iEdgedWidth;
165 :     const uint32_t rounding = data->rounding;
166 :     const int halfpel_x = x/2;
167 :     const int halfpel_y = y/2;
168 :     const uint8_t *ref1, *ref2, *ref3, *ref4;
169 :    
170 :     ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
171 :     switch( ((x&1)<<1) + (y&1) ) {
172 :     case 3:
173 :     /*
174 :     * x and y in qpel resolution - the "corners" (top left/right and
175 :     * bottom left/right) during qpel refinement
176 :     */
177 :     ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
178 :     ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
179 :     ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
180 :     interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
181 :     interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
182 :     interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
183 :     interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
184 :     break;
185 :    
186 :     case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
187 :     ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
188 :     interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
189 :     interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
190 :     interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
191 :     interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
192 :     break;
193 :    
194 :     case 2: /* x qpel, y halfpel - left or right during qpel refinement */
195 :     ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
196 :     interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
197 :     interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
198 :     interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
199 :     interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
200 :     break;
201 :    
202 :    
203 :     default: /* pure halfpel position */
204 :     return (uint8_t *) ref1;
205 :     }
206 :     return Reference;
207 :     }
208 :    
209 :     void
210 :     xvid_me_AdvDiamondSearch(int x, int y, SearchData * const data,
211 :     int bDirection, CheckFunc * const CheckCandidate)
212 :     {
213 :    
214 :     /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
215 :    
216 :     unsigned int * const iDirection = &data->dir;
217 :    
218 :     for(;;) { /* forever */
219 :     *iDirection = 0;
220 :     if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
221 :     if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
222 :     if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
223 :     if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
224 :    
225 :     /* now we're doing diagonal checks near our candidate */
226 :    
227 :     if (*iDirection) { /* if anything found */
228 :     bDirection = *iDirection;
229 :     *iDirection = 0;
230 :     x = data->currentMV->x; y = data->currentMV->y;
231 :     if (bDirection & 3) { /* our candidate is left or right */
232 :     CHECK_CANDIDATE(x, y + iDiamondSize, 8);
233 :     CHECK_CANDIDATE(x, y - iDiamondSize, 4);
234 :     } else { /* what remains here is up or down */
235 :     CHECK_CANDIDATE(x + iDiamondSize, y, 2);
236 :     CHECK_CANDIDATE(x - iDiamondSize, y, 1);
237 :     }
238 :    
239 :     if (*iDirection) {
240 :     bDirection += *iDirection;
241 :     x = data->currentMV->x; y = data->currentMV->y;
242 :     }
243 :     } else { /* about to quit, eh? not so fast.... */
244 :     switch (bDirection) {
245 :     case 2:
246 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
247 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
248 :     break;
249 :     case 1:
250 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
251 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
252 :     break;
253 :     case 2 + 4:
254 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
255 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
256 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
257 :     break;
258 :     case 4:
259 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
260 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
261 :     break;
262 :     case 8:
263 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
264 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
265 :     break;
266 :     case 1 + 4:
267 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
268 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
269 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
270 :     break;
271 :     case 2 + 8:
272 : syskin 1.9 CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
273 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
274 : edgomez 1.2 CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
275 :     break;
276 :     case 1 + 8:
277 : syskin 1.9 CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
278 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
279 : edgomez 1.2 CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
280 :     break;
281 :     default: /* 1+2+4+8 == we didn't find anything at all */
282 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
283 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
284 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
285 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
286 :     break;
287 :     }
288 :     if (!*iDirection) break; /* ok, the end. really */
289 :     bDirection = *iDirection;
290 :     x = data->currentMV->x; y = data->currentMV->y;
291 :     }
292 :     }
293 :     }
294 :    
295 :     void
296 :     xvid_me_SquareSearch(int x, int y, SearchData * const data,
297 :     int bDirection, CheckFunc * const CheckCandidate)
298 :     {
299 :     unsigned int * const iDirection = &data->dir;
300 :    
301 :     do {
302 :     *iDirection = 0;
303 :     if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1+16+64);
304 :     if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2+32+128);
305 :     if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4+16+32);
306 :     if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8+64+128);
307 :     if (bDirection & 16) CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1+4+16+32+64);
308 :     if (bDirection & 32) CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2+4+16+32+128);
309 :     if (bDirection & 64) CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1+8+16+64+128);
310 :     if (bDirection & 128) CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2+8+32+64+128);
311 :    
312 :     bDirection = *iDirection;
313 :     x = data->currentMV->x; y = data->currentMV->y;
314 :     } while (*iDirection);
315 :     }
316 :    
317 :     void
318 :     xvid_me_DiamondSearch(int x, int y, SearchData * const data,
319 :     int bDirection, CheckFunc * const CheckCandidate)
320 :     {
321 :    
322 :     /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
323 :    
324 :     unsigned int * const iDirection = &data->dir;
325 :    
326 : chl 1.8 for (;;) {
327 : edgomez 1.2 *iDirection = 0;
328 :     if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
329 :     if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
330 :     if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
331 :     if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
332 :    
333 : chl 1.8 if (*iDirection == 0)
334 :     break;
335 :    
336 : edgomez 1.2 /* now we're doing diagonal checks near our candidate */
337 : syskin 1.6 bDirection = *iDirection;
338 : chl 1.8 x = data->currentMV->x; y = data->currentMV->y;
339 :     if (bDirection & 3) { /* our candidate is left or right */
340 :     CHECK_CANDIDATE(x, y + iDiamondSize, 8);
341 :     CHECK_CANDIDATE(x, y - iDiamondSize, 4);
342 :     } else { /* what remains here is up or down */
343 :     CHECK_CANDIDATE(x + iDiamondSize, y, 2);
344 :     CHECK_CANDIDATE(x - iDiamondSize, y, 1);
345 : edgomez 1.2 }
346 : chl 1.8 bDirection |= *iDirection;
347 :     x = data->currentMV->x; y = data->currentMV->y;
348 : edgomez 1.2 }
349 :     }
350 :    
351 :     void
352 : syskin 1.5 xvid_me_SubpelRefine(VECTOR centerMV, SearchData * const data, CheckFunc * const CheckCandidate, int dir)
353 : edgomez 1.2 {
354 :     /* Do a half-pel or q-pel refinement */
355 :    
356 : syskin 1.4 CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, dir);
357 :     CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, dir);
358 :     CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, dir);
359 :     CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, dir);
360 :     CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, dir);
361 :     CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, dir);
362 :     CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, dir);
363 :     CHECK_CANDIDATE(centerMV.x - 1, centerMV.y - 1, dir);
364 :     }
365 :    
366 :     #define CHECK_CANDIDATE_2ndBEST(X, Y, DIR) { \
367 :     *data->iMinSAD = s_best2; \
368 :     CheckCandidate((X),(Y), data, direction); \
369 :     if (data->iMinSAD[0] < s_best) { \
370 :     s_best2 = s_best; \
371 :     s_best = data->iMinSAD[0]; \
372 :     v_best2 = v_best; \
373 :     v_best.x = X; v_best.y = Y; \
374 :     dir = DIR; \
375 :     } else if (data->iMinSAD[0] < s_best2) { \
376 :     s_best2 = data->iMinSAD[0]; \
377 :     v_best2.x = X; v_best2.y = Y; \
378 :     } \
379 : edgomez 1.2 }
380 :    
381 :     void
382 : syskin 1.4 FullRefine_Fast(SearchData * data, CheckFunc * CheckCandidate, int direction)
383 : edgomez 1.2 {
384 : syskin 1.4 /* Do a fast h-pel and then q-pel refinement */
385 :    
386 :     int32_t s_best = data->iMinSAD[0], s_best2 = 256*4096;
387 :     VECTOR v_best, v_best2;
388 :     int dir = 0, xo2, yo2, best_halfpel, b_cbp;
389 :    
390 :     int xo = 2*data->currentMV[0].x, yo = 2*data->currentMV[0].y;
391 :    
392 : Skal 1.12 data->currentQMV[0].x = v_best.x = v_best2.x = xo;
393 :     data->currentQMV[0].y = v_best.y = v_best2.y = yo;
394 : syskin 1.4
395 :     data->qpel_precision = 1;
396 :    
397 :     /* halfpel refinement: check 8 neighbours, but keep the second best SAD as well */
398 :     CHECK_CANDIDATE_2ndBEST(xo - 2, yo, 1+16+64);
399 :     CHECK_CANDIDATE_2ndBEST(xo + 2, yo, 2+32+128);
400 :     CHECK_CANDIDATE_2ndBEST(xo, yo - 2, 4+16+32);
401 :     CHECK_CANDIDATE_2ndBEST(xo, yo + 2, 8+64+128);
402 :     CHECK_CANDIDATE_2ndBEST(xo - 2, yo - 2, 1+4+16+32+64);
403 :     CHECK_CANDIDATE_2ndBEST(xo + 2, yo - 2, 2+4+16+32+128);
404 :     CHECK_CANDIDATE_2ndBEST(xo - 2, yo + 2, 1+8+16+64+128);
405 :     CHECK_CANDIDATE_2ndBEST(xo + 2, yo + 2, 2+8+32+64+128);
406 :    
407 :     xo = v_best.x; yo = v_best.y, b_cbp = data->cbp[0];
408 :    
409 :     /* we need all 8 neighbours *of best hpel position found above* checked for 2nd best
410 :     let's check the missing ones */
411 :    
412 :     /* on rare occasions, 1st best and 2nd best are far away, and 2nd best is not 1st best's neighbour.
413 :     to simplify stuff, we'll forget that evil 2nd best and make a full search for a new 2nd best */
414 :     /* todo. we should check the missing neighbours first, maybe they'll give us 2nd best which is even better
415 :     than the infamous one. in that case, we will not have to re-check the other neighbours */
416 :    
417 :     if (abs(v_best.x - v_best2.x) > 2 || abs(v_best.y - v_best2.y) > 2) { /* v_best2 is useless */
418 :     data->iMinSAD[0] = 256*4096;
419 :     dir = ~0; /* all */
420 :     } else {
421 :     data->iMinSAD[0] = s_best2;
422 :     data->currentQMV[0] = v_best2;
423 :     }
424 : edgomez 1.2
425 : syskin 1.4 if (dir & 1) CHECK_CANDIDATE( xo - 2, yo, direction);
426 :     if (dir & 2) CHECK_CANDIDATE( xo + 2, yo, direction);
427 :     if (dir & 4) CHECK_CANDIDATE( xo, yo - 2, direction);
428 :     if (dir & 8) CHECK_CANDIDATE( xo, yo + 2, direction);
429 :     if (dir & 16) CHECK_CANDIDATE( xo - 2, yo - 2, direction);
430 :     if (dir & 32) CHECK_CANDIDATE( xo + 2, yo - 2, direction);
431 :     if (dir & 64) CHECK_CANDIDATE( xo - 2, yo + 2, direction);
432 :     if (dir & 128) CHECK_CANDIDATE( xo + 2, yo + 2, direction);
433 :    
434 :     /* read the position of 2nd best */
435 :     v_best2 = data->currentQMV[0];
436 :    
437 :     /* after second_best has been found, go back to best vector */
438 :    
439 :     data->currentQMV[0].x = xo;
440 :     data->currentQMV[0].y = yo;
441 :     data->cbp[0] = b_cbp;
442 :    
443 :     data->currentMV[0].x = xo/2;
444 :     data->currentMV[0].y = yo/2;
445 :     data->iMinSAD[0] = best_halfpel = s_best;
446 :    
447 :     xo2 = v_best2.x;
448 :     yo2 = v_best2.y;
449 :     s_best2 = 256*4096;
450 : edgomez 1.2
451 :     if (yo == yo2) {
452 : syskin 1.4 CHECK_CANDIDATE_2ndBEST((xo+xo2)>>1, yo, 0);
453 :     CHECK_CANDIDATE_2ndBEST(xo, yo-1, 0);
454 :     CHECK_CANDIDATE_2ndBEST(xo, yo+1, 0);
455 :     data->currentQMV[0] = v_best;
456 :     data->iMinSAD[0] = s_best;
457 :    
458 :     if(best_halfpel <= s_best2) return;
459 :    
460 :     if(data->currentQMV[0].x == v_best2.x) {
461 :     CHECK_CANDIDATE((xo+xo2)>>1, yo-1, direction);
462 :     CHECK_CANDIDATE((xo+xo2)>>1, yo+1, direction);
463 : edgomez 1.2 } else {
464 :     CHECK_CANDIDATE((xo+xo2)>>1,
465 : syskin 1.4 (data->currentQMV[0].x == xo) ? data->currentQMV[0].y : v_best2.y, direction);
466 : edgomez 1.2 }
467 :     return;
468 :     }
469 :    
470 :     if (xo == xo2) {
471 : syskin 1.4 CHECK_CANDIDATE_2ndBEST(xo, (yo+yo2)>>1, 0);
472 :     CHECK_CANDIDATE_2ndBEST(xo-1, yo, 0);
473 :     CHECK_CANDIDATE_2ndBEST(xo+1, yo, 0);
474 :     data->currentQMV[0] = v_best;
475 :     data->iMinSAD[0] = s_best;
476 :    
477 :     if(best_halfpel <= s_best2) return;
478 :    
479 :     if(data->currentQMV[0].y == v_best2.y) {
480 :     CHECK_CANDIDATE(xo-1, (yo+yo2)>>1, direction);
481 :     CHECK_CANDIDATE(xo+1, (yo+yo2)>>1, direction);
482 : edgomez 1.2 } else {
483 : syskin 1.4 CHECK_CANDIDATE((data->currentQMV[0].y == yo) ? data->currentQMV[0].x : v_best2.x, (yo+yo2)>>1, direction);
484 : edgomez 1.2 }
485 :     return;
486 :     }
487 :    
488 : syskin 1.4 CHECK_CANDIDATE_2ndBEST(xo, (yo+yo2)>>1, 0);
489 :     CHECK_CANDIDATE_2ndBEST((xo+xo2)>>1, yo, 0);
490 :     data->currentQMV[0] = v_best;
491 :     data->iMinSAD[0] = s_best;
492 :    
493 :     if(best_halfpel <= s_best2) return;
494 : edgomez 1.2
495 : syskin 1.4 CHECK_CANDIDATE((xo+xo2)>>1, (yo+yo2)>>1, direction);
496 : edgomez 1.2
497 :     }
498 : syskin 1.10
499 :     /* it's the positive max, so "32" needs fcode of 2, not 1 */
500 :     unsigned int
501 :     getMinFcode(const int MVmax)
502 :     {
503 :     unsigned int fcode;
504 :     for (fcode = 1; (16 << fcode) <= MVmax; fcode++);
505 :     return fcode;
506 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4