[svn] / branches / dev-api-4 / xvidcore / src / motion / estimation_common.c Repository:
ViewVC logotype

Annotation of /branches/dev-api-4/xvidcore/src/motion/estimation_common.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1142 - (view) (download)

1 : edgomez 1142 /*****************************************************************************
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 :     * $Id: estimation_common.c,v 1.1.2.1 2003-09-10 22:18:59 edgomez Exp $
25 :     *
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 :     { 0 ,(int)(1.00235 * NEIGH_TEND_16X16 + 0.5),
59 :     (int)(1.15582*NEIGH_TEND_16X16 + 0.5), (int)(1.31976*NEIGH_TEND_16X16 + 0.5),
60 :     (int)(1.49591*NEIGH_TEND_16X16 + 0.5), (int)(1.68601*NEIGH_TEND_16X16 + 0.5),
61 :     (int)(1.89187*NEIGH_TEND_16X16 + 0.5), (int)(2.11542*NEIGH_TEND_16X16 + 0.5),
62 :     (int)(2.35878*NEIGH_TEND_16X16 + 0.5), (int)(2.62429*NEIGH_TEND_16X16 + 0.5),
63 :     (int)(2.91455*NEIGH_TEND_16X16 + 0.5), (int)(3.23253*NEIGH_TEND_16X16 + 0.5),
64 :     (int)(3.58158*NEIGH_TEND_16X16 + 0.5), (int)(3.96555*NEIGH_TEND_16X16 + 0.5),
65 :     (int)(4.38887*NEIGH_TEND_16X16 + 0.5), (int)(4.85673*NEIGH_TEND_16X16 + 0.5),
66 :     (int)(5.37519*NEIGH_TEND_16X16 + 0.5), (int)(5.95144*NEIGH_TEND_16X16 + 0.5),
67 :     (int)(6.59408*NEIGH_TEND_16X16 + 0.5), (int)(7.31349*NEIGH_TEND_16X16 + 0.5),
68 :     (int)(8.12242*NEIGH_TEND_16X16 + 0.5), (int)(9.03669*NEIGH_TEND_16X16 + 0.5),
69 :     (int)(10.0763*NEIGH_TEND_16X16 + 0.5), (int)(11.2669*NEIGH_TEND_16X16 + 0.5),
70 :     (int)(12.6426*NEIGH_TEND_16X16 + 0.5), (int)(14.2493*NEIGH_TEND_16X16 + 0.5),
71 :     (int)(16.1512*NEIGH_TEND_16X16 + 0.5), (int)(18.442*NEIGH_TEND_16X16 + 0.5),
72 :     (int)(21.2656*NEIGH_TEND_16X16 + 0.5), (int)(24.8580*NEIGH_TEND_16X16 + 0.5),
73 :     (int)(29.6436*NEIGH_TEND_16X16 + 0.5), (int)(36.4949*NEIGH_TEND_16X16 + 0.5)
74 :     };
75 :    
76 :     /*****************************************************************************
77 :     * Code
78 :     ****************************************************************************/
79 :    
80 :     int32_t
81 :     xvid_me_ChromaSAD(const int dx, const int dy, const 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->temp[5] && dy == data->temp[6]) return data->temp[7]; /* it has been checked recently */
89 :     data->temp[5] = dx; data->temp[6] = dy; /* backup */
90 :    
91 :     switch (((dx & 1) << 1) | (dy & 1)) {
92 :     case 0:
93 :     sad = sad8(data->CurU, data->RefP[4] + offset, stride);
94 :     sad += sad8(data->CurV, data->RefP[5] + offset, stride);
95 :     break;
96 :     case 1:
97 :     next = stride;
98 :     case 2:
99 :     sad = sad8bi(data->CurU, data->RefP[4] + offset, data->RefP[4] + offset + next, stride);
100 :     sad += sad8bi(data->CurV, data->RefP[5] + offset, data->RefP[5] + offset + next, stride);
101 :     break;
102 :     default:
103 :     interpolate8x8_halfpel_hv(data->RefQ, data->RefP[4] + offset, stride, data->rounding);
104 :     sad = sad8(data->CurU, data->RefQ, stride);
105 :    
106 :     interpolate8x8_halfpel_hv(data->RefQ, data->RefP[5] + offset, stride, data->rounding);
107 :     sad += sad8(data->CurV, data->RefQ, stride);
108 :     break;
109 :     }
110 :     data->temp[7] = sad; /* backup, part 2 */
111 :     return sad;
112 :     }
113 :    
114 :     uint8_t *
115 :     xvid_me_interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
116 :     {
117 :     /* create or find a qpel-precision reference picture; return pointer to it */
118 :     uint8_t * Reference = data->RefQ + 16*dir;
119 :     const uint32_t iEdgedWidth = data->iEdgedWidth;
120 :     const uint32_t rounding = data->rounding;
121 :     const int halfpel_x = x/2;
122 :     const int halfpel_y = y/2;
123 :     const uint8_t *ref1, *ref2, *ref3, *ref4;
124 :    
125 :     ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
126 :     ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
127 :     switch( ((x&1)<<1) + (y&1) ) {
128 :     case 3: /* x and y in qpel resolution - the "corners" (top left/right and */
129 :     /* bottom left/right) during qpel refinement */
130 :     ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
131 :     ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
132 :     ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
133 :     ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
134 :     ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
135 :     ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
136 :     interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
137 :     break;
138 :    
139 :     case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
140 :     ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
141 :     ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
142 :     interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
143 :     break;
144 :    
145 :     case 2: /* x qpel, y halfpel - left or right during qpel refinement */
146 :     ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
147 :     ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
148 :     interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
149 :     break;
150 :    
151 :     default: /* pure halfpel position */
152 :     return (uint8_t *) ref1;
153 :    
154 :     }
155 :     return Reference;
156 :     }
157 :    
158 :     uint8_t *
159 :     xvid_me_interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
160 :     {
161 :     /* create or find a qpel-precision reference picture; return pointer to it */
162 :     uint8_t * Reference = data->RefQ + 16*dir;
163 :     const uint32_t iEdgedWidth = data->iEdgedWidth;
164 :     const uint32_t rounding = data->rounding;
165 :     const int halfpel_x = x/2;
166 :     const int halfpel_y = y/2;
167 :     const uint8_t *ref1, *ref2, *ref3, *ref4;
168 :    
169 :     ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
170 :     switch( ((x&1)<<1) + (y&1) ) {
171 :     case 3:
172 :     /*
173 :     * x and y in qpel resolution - the "corners" (top left/right and
174 :     * bottom left/right) during qpel refinement
175 :     */
176 :     ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
177 :     ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
178 :     ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
179 :     interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
180 :     interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
181 :     interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
182 :     interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
183 :     break;
184 :    
185 :     case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
186 :     ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
187 :     interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
188 :     interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
189 :     interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
190 :     interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
191 :     break;
192 :    
193 :     case 2: /* x qpel, y halfpel - left or right during qpel refinement */
194 :     ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
195 :     interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
196 :     interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
197 :     interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
198 :     interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
199 :     break;
200 :    
201 :    
202 :     default: /* pure halfpel position */
203 :     return (uint8_t *) ref1;
204 :     }
205 :     return Reference;
206 :     }
207 :    
208 :     void
209 :     xvid_me_AdvDiamondSearch(int x, int y, const SearchData * const data,
210 :     int bDirection, CheckFunc * const CheckCandidate)
211 :     {
212 :    
213 :     /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
214 :    
215 :     unsigned int * const iDirection = data->dir;
216 :    
217 :     for(;;) { /* forever */
218 :     *iDirection = 0;
219 :     if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
220 :     if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
221 :     if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
222 :     if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
223 :    
224 :     /* now we're doing diagonal checks near our candidate */
225 :    
226 :     if (*iDirection) { /* if anything found */
227 :     bDirection = *iDirection;
228 :     *iDirection = 0;
229 :     x = data->currentMV->x; y = data->currentMV->y;
230 :     if (bDirection & 3) { /* our candidate is left or right */
231 :     CHECK_CANDIDATE(x, y + iDiamondSize, 8);
232 :     CHECK_CANDIDATE(x, y - iDiamondSize, 4);
233 :     } else { /* what remains here is up or down */
234 :     CHECK_CANDIDATE(x + iDiamondSize, y, 2);
235 :     CHECK_CANDIDATE(x - iDiamondSize, y, 1);
236 :     }
237 :    
238 :     if (*iDirection) {
239 :     bDirection += *iDirection;
240 :     x = data->currentMV->x; y = data->currentMV->y;
241 :     }
242 :     } else { /* about to quit, eh? not so fast.... */
243 :     switch (bDirection) {
244 :     case 2:
245 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
246 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
247 :     break;
248 :     case 1:
249 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
250 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
251 :     break;
252 :     case 2 + 4:
253 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
254 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
255 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
256 :     break;
257 :     case 4:
258 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
259 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
260 :     break;
261 :     case 8:
262 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
263 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
264 :     break;
265 :     case 1 + 4:
266 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
267 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
268 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
269 :     break;
270 :     case 2 + 8:
271 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
272 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
273 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
274 :     break;
275 :     case 1 + 8:
276 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
277 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
278 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
279 :     break;
280 :     default: /* 1+2+4+8 == we didn't find anything at all */
281 :     CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
282 :     CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
283 :     CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
284 :     CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
285 :     break;
286 :     }
287 :     if (!*iDirection) break; /* ok, the end. really */
288 :     bDirection = *iDirection;
289 :     x = data->currentMV->x; y = data->currentMV->y;
290 :     }
291 :     }
292 :     }
293 :    
294 :     void
295 :     xvid_me_SquareSearch(int x, int y, const SearchData * const data,
296 :     int bDirection, CheckFunc * const CheckCandidate)
297 :     {
298 :     unsigned int * const iDirection = data->dir;
299 :    
300 :     do {
301 :     *iDirection = 0;
302 :     if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1+16+64);
303 :     if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2+32+128);
304 :     if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4+16+32);
305 :     if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8+64+128);
306 :     if (bDirection & 16) CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1+4+16+32+64);
307 :     if (bDirection & 32) CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2+4+16+32+128);
308 :     if (bDirection & 64) CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1+8+16+64+128);
309 :     if (bDirection & 128) CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2+8+32+64+128);
310 :    
311 :     bDirection = *iDirection;
312 :     x = data->currentMV->x; y = data->currentMV->y;
313 :     } while (*iDirection);
314 :     }
315 :    
316 :     void
317 :     xvid_me_DiamondSearch(int x, int y, const SearchData * const data,
318 :     int bDirection, CheckFunc * const CheckCandidate)
319 :     {
320 :    
321 :     /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
322 :    
323 :     unsigned int * const iDirection = data->dir;
324 :    
325 :     do {
326 :     *iDirection = 0;
327 :     if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
328 :     if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
329 :     if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
330 :     if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
331 :    
332 :     /* now we're doing diagonal checks near our candidate */
333 :    
334 :     if (*iDirection) { /* checking if anything found */
335 :     bDirection = *iDirection;
336 :     *iDirection = 0;
337 :     x = data->currentMV->x; y = data->currentMV->y;
338 :     if (bDirection & 3) { /* our candidate is left or right */
339 :     CHECK_CANDIDATE(x, y + iDiamondSize, 8);
340 :     CHECK_CANDIDATE(x, y - iDiamondSize, 4);
341 :     } else { /* what remains here is up or down */
342 :     CHECK_CANDIDATE(x + iDiamondSize, y, 2);
343 :     CHECK_CANDIDATE(x - iDiamondSize, y, 1);
344 :     }
345 :     bDirection += *iDirection;
346 :     x = data->currentMV->x; y = data->currentMV->y;
347 :     }
348 :     }
349 :     while (*iDirection);
350 :     }
351 :    
352 :     void
353 :     xvid_me_SubpelRefine(const SearchData * const data, CheckFunc * const CheckCandidate)
354 :     {
355 :     /* Do a half-pel or q-pel refinement */
356 :     const VECTOR centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
357 :    
358 :     CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, 0);
359 :     CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, 0);
360 :     CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, 0);
361 :     CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, 0);
362 :     CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, 0);
363 :     CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, 0);
364 :     CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, 0);
365 :     CHECK_CANDIDATE(centerMV.x - 1, centerMV.y - 1, 0);
366 :     }
367 :    

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