[svn] / trunk / xvidcore / src / motion / estimation_gmc.c Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/src/motion/estimation_gmc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1988 - (view) (download)

1 : edgomez 1382 /*****************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC
4 :     * - Global Motion Estimation -
5 :     *
6 :     * Copyright(C) 2003 Christoph Lampert <gruel@web.de>
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 : Isibaar 1988 * $Id$
23 : edgomez 1382 *
24 :     ****************************************************************************/
25 :    
26 :     #include <assert.h>
27 :     #include <stdio.h>
28 :     #include <stdlib.h>
29 :     #include <string.h>
30 :     #include <math.h>
31 :    
32 :     #include "../encoder.h"
33 :     #include "../prediction/mbprediction.h"
34 :     #include "estimation.h"
35 :     #include "motion.h"
36 :     #include "sad.h"
37 :     #include "gmc.h"
38 :     #include "../utils/emms.h"
39 :     #include "motion_inlines.h"
40 :    
41 :     static void
42 :     CheckCandidate16I(const int x, const int y, SearchData * const data, const unsigned int Direction)
43 :     {
44 :     int sad;
45 :     const uint8_t * Reference;
46 :    
47 :     if ( (x > data->max_dx) || ( x < data->min_dx)
48 :     || (y > data->max_dy) || (y < data->min_dy) ) return;
49 :    
50 :     Reference = GetReference(x, y, data);
51 :    
52 :     sad = sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);
53 :    
54 :     if (sad < data->iMinSAD[0]) {
55 :     data->iMinSAD[0] = sad;
56 :     data->currentMV[0].x = x; data->currentMV[0].y = y;
57 :     data->dir = Direction;
58 :     }
59 :     }
60 :    
61 :     static __inline void
62 :     GMEanalyzeMB ( const uint8_t * const pCur,
63 :     const uint8_t * const pRef,
64 :     const uint8_t * const pRefH,
65 :     const uint8_t * const pRefV,
66 :     const uint8_t * const pRefHV,
67 :     const int x,
68 :     const int y,
69 :     const MBParam * const pParam,
70 :     MACROBLOCK * const pMBs,
71 : Isibaar 1913 SearchData * const Data,
72 :     const int bound)
73 : edgomez 1382 {
74 :    
75 :     MACROBLOCK * const pMB = &pMBs[x + y * pParam->mb_width];
76 :    
77 :     Data->iMinSAD[0] = MV_MAX_ERROR;
78 :    
79 : Isibaar 1913 Data->predMV = get_pmv2(pMBs, pParam->mb_width, bound, x, y, 0);
80 : edgomez 1382
81 :     get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
82 : syskin 1564 pParam->width, pParam->height, 16, 1);
83 : edgomez 1382
84 :     Data->Cur = pCur + 16*(x + y * pParam->edged_width);
85 :     Data->RefP[0] = pRef + 16*(x + y * pParam->edged_width);
86 :     Data->RefP[1] = pRefV + 16*(x + y * pParam->edged_width);
87 :     Data->RefP[2] = pRefH + 16*(x + y * pParam->edged_width);
88 :     Data->RefP[3] = pRefHV + 16*(x + y * pParam->edged_width);
89 :    
90 :     Data->currentMV[0].x = Data->currentMV[0].y = 0;
91 :     CheckCandidate16I(0, 0, Data, 255);
92 :    
93 :     if ( (Data->predMV.x !=0) || (Data->predMV.y != 0) )
94 :     CheckCandidate16I(Data->predMV.x, Data->predMV.y, Data, 255);
95 :    
96 :     xvid_me_DiamondSearch(Data->currentMV[0].x, Data->currentMV[0].y, Data, 255, CheckCandidate16I);
97 :    
98 : syskin 1478 xvid_me_SubpelRefine(Data->currentMV[0], Data, CheckCandidate16I, 0);
99 : edgomez 1382
100 :    
101 :     /* for QPel halfpel positions are worse than in halfpel mode :( */
102 :     /* if (Data->qpel) {
103 :     Data->currentQMV->x = 2*Data->currentMV->x;
104 :     Data->currentQMV->y = 2*Data->currentMV->y;
105 :     Data->qpel_precision = 1;
106 :     get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
107 :     pParam->width, pParam->height, iFcode, 2, 0);
108 :     SubpelRefine(Data);
109 :     }
110 :     */
111 :    
112 :     pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
113 :     pMB->sad16 = Data->iMinSAD[0];
114 :     pMB->mode = MODE_INTER;
115 : syskin 1564 pMB->sad16 += 10*d_mv_bits(pMB->mvs[0].x, pMB->mvs[0].y, Data->predMV, Data->iFcode, 0);
116 : edgomez 1382 return;
117 :     }
118 :    
119 :    
120 :     void
121 :     GMEanalysis(const MBParam * const pParam,
122 :     const FRAMEINFO * const current,
123 :     const FRAMEINFO * const reference,
124 :     const IMAGE * const pRefH,
125 :     const IMAGE * const pRefV,
126 : Isibaar 1913 const IMAGE * const pRefHV,
127 :     const int num_slices)
128 : edgomez 1382 {
129 :     uint32_t x, y;
130 :     MACROBLOCK * const pMBs = current->mbs;
131 :     const IMAGE * const pCurrent = &current->image;
132 :     const IMAGE * const pReference = &reference->image;
133 : Isibaar 1913 int bound = 0;
134 :     const uint32_t mb_width = pParam->mb_width;
135 :     const uint32_t mb_height = pParam->mb_height;
136 : edgomez 1382
137 :     SearchData Data;
138 :     memset(&Data, 0, sizeof(SearchData));
139 :    
140 :     Data.iEdgedWidth = pParam->edged_width;
141 :     Data.rounding = pParam->m_rounding_type;
142 :    
143 :     Data.iFcode = current->fcode;
144 :    
145 :     if (sadInit) (*sadInit) ();
146 :    
147 :     for (y = 0; y < pParam->mb_height; y ++) {
148 : Isibaar 1913 bound = mb_width * ((((y*num_slices) / mb_height) * mb_height + (num_slices-1))/ num_slices);
149 : edgomez 1382 for (x = 0; x < pParam->mb_width; x ++) {
150 : Isibaar 1913 GMEanalyzeMB(pCurrent->y, pReference->y, pRefH->y, pRefV->y, pRefHV->y, x, y, pParam, pMBs, &Data, bound);
151 : edgomez 1382 }
152 :     }
153 :     return;
154 :     }
155 :    
156 :     WARPPOINTS
157 :     GlobalMotionEst(MACROBLOCK * const pMBs,
158 :     const MBParam * const pParam,
159 :     const FRAMEINFO * const current,
160 :     const FRAMEINFO * const reference,
161 :     const IMAGE * const pRefH,
162 :     const IMAGE * const pRefV,
163 : Isibaar 1913 const IMAGE * const pRefHV,
164 :     const int num_slices)
165 : edgomez 1382 {
166 :    
167 :     const int deltax=8; /* upper bound for difference between a MV and it's neighbour MVs */
168 :     const int deltay=8;
169 :     const unsigned int gradx=512; /* lower bound for gradient in MB (ignore "flat" blocks) */
170 :     const unsigned int grady=512;
171 :    
172 :     double sol[4] = { 0., 0., 0., 0. };
173 :    
174 :     WARPPOINTS gmc;
175 :    
176 :     uint32_t mx, my;
177 :    
178 :     int MBh = pParam->mb_height;
179 :     int MBw = pParam->mb_width;
180 :     const int minblocks = 9; /* was = /MBh*MBw/32+3 */ /* just some reasonable number 3% + 3 */
181 :     const int maxblocks = MBh*MBw/4; /* just some reasonable number 3% + 3 */
182 :    
183 :     int num=0;
184 :     int oldnum;
185 :    
186 :     gmc.duv[0].x = gmc.duv[0].y = gmc.duv[1].x = gmc.duv[1].y = gmc.duv[2].x = gmc.duv[2].y = 0;
187 :    
188 : Isibaar 1913 GMEanalysis(pParam,current, reference, pRefH, pRefV, pRefHV, num_slices);
189 : edgomez 1382
190 :     /* block based ME isn't done, yet, so do a quick presearch */
191 :    
192 :     /* filter mask of all blocks */
193 :    
194 :     for (my = 0; my < (uint32_t)MBh; my++)
195 :     for (mx = 0; mx < (uint32_t)MBw; mx++)
196 :     {
197 :     const int mbnum = mx + my * MBw;
198 :     pMBs[mbnum].mcsel = 0;
199 :     }
200 :    
201 :    
202 :     for (my = 1; my < (uint32_t)MBh-1; my++) /* ignore boundary blocks */
203 :     for (mx = 1; mx < (uint32_t)MBw-1; mx++) /* theirs MVs are often wrong */
204 :     {
205 :     const int mbnum = mx + my * MBw;
206 :     MACROBLOCK *const pMB = &pMBs[mbnum];
207 :     const VECTOR mv = pMB->mvs[0];
208 :    
209 :     /* don't use object boundaries */
210 :     if ( (abs(mv.x - (pMB-1)->mvs[0].x) < deltax)
211 :     && (abs(mv.y - (pMB-1)->mvs[0].y) < deltay)
212 :     && (abs(mv.x - (pMB+1)->mvs[0].x) < deltax)
213 :     && (abs(mv.y - (pMB+1)->mvs[0].y) < deltay)
214 :     && (abs(mv.x - (pMB-MBw)->mvs[0].x) < deltax)
215 :     && (abs(mv.y - (pMB-MBw)->mvs[0].y) < deltay)
216 :     && (abs(mv.x - (pMB+MBw)->mvs[0].x) < deltax)
217 :     && (abs(mv.y - (pMB+MBw)->mvs[0].y) < deltay) )
218 :     { const int iEdgedWidth = pParam->edged_width;
219 :     const uint8_t *const pCur = current->image.y + 16*(my*iEdgedWidth + mx);
220 :     if ( (sad16 ( pCur, pCur+1 , iEdgedWidth, 65536) >= gradx )
221 :     && (sad16 ( pCur, pCur+iEdgedWidth, iEdgedWidth, 65536) >= grady ) )
222 :     { pMB->mcsel = 1;
223 :     num++;
224 :     }
225 :    
226 :     /* only use "structured" blocks */
227 :     }
228 :     }
229 :     emms();
230 :    
231 :     /* further filtering would be possible, but during iteration, remaining
232 :     outliers usually are removed, too */
233 :    
234 :     if (num>= minblocks)
235 :     do { /* until convergence */
236 :     double DtimesF[4];
237 :     double a,b,c,n,invdenom;
238 :     double meanx,meany;
239 :    
240 :     a = b = c = n = 0;
241 :     DtimesF[0] = DtimesF[1] = DtimesF[2] = DtimesF[3] = 0.;
242 :     for (my = 1; my < (uint32_t)MBh-1; my++)
243 :     for (mx = 1; mx < (uint32_t)MBw-1; mx++)
244 :     {
245 :     const int mbnum = mx + my * MBw;
246 :     const VECTOR mv = pMBs[mbnum].mvs[0];
247 :    
248 :     if (!pMBs[mbnum].mcsel)
249 :     continue;
250 :    
251 :     n++;
252 :     a += 16*mx+8;
253 :     b += 16*my+8;
254 :     c += (16*mx+8)*(16*mx+8)+(16*my+8)*(16*my+8);
255 :    
256 :     DtimesF[0] += (double)mv.x;
257 :     DtimesF[1] += (double)mv.x*(16*mx+8) + (double)mv.y*(16*my+8);
258 :     DtimesF[2] += (double)mv.x*(16*my+8) - (double)mv.y*(16*mx+8);
259 :     DtimesF[3] += (double)mv.y;
260 :     }
261 :    
262 :     invdenom = a*a+b*b-c*n;
263 :    
264 :     /* Solve the system: sol = (D'*E*D)^{-1} D'*E*F */
265 :     /* D'*E*F has been calculated in the same loop as matrix */
266 :    
267 :     sol[0] = -c*DtimesF[0] + a*DtimesF[1] + b*DtimesF[2];
268 :     sol[1] = a*DtimesF[0] - n*DtimesF[1] + b*DtimesF[3];
269 :     sol[2] = b*DtimesF[0] - n*DtimesF[2] - a*DtimesF[3];
270 :     sol[3] = b*DtimesF[1] - a*DtimesF[2] - c*DtimesF[3];
271 :    
272 :     sol[0] /= invdenom;
273 :     sol[1] /= invdenom;
274 :     sol[2] /= invdenom;
275 :     sol[3] /= invdenom;
276 :    
277 :     meanx = meany = 0.;
278 :     oldnum = 0;
279 :     for (my = 1; my < (uint32_t)MBh-1; my++)
280 :     for (mx = 1; mx < (uint32_t)MBw-1; mx++)
281 :     {
282 :     const int mbnum = mx + my * MBw;
283 :     const VECTOR mv = pMBs[mbnum].mvs[0];
284 :    
285 :     if (!pMBs[mbnum].mcsel)
286 :     continue;
287 :    
288 :     oldnum++;
289 :     meanx += fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - (double)mv.x );
290 :     meany += fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - (double)mv.y );
291 :     }
292 :    
293 :     if (4*meanx > oldnum) /* better fit than 0.25 (=1/4pel) is useless */
294 :     meanx /= oldnum;
295 :     else
296 :     meanx = 0.25;
297 :    
298 :     if (4*meany > oldnum)
299 :     meany /= oldnum;
300 :     else
301 :     meany = 0.25;
302 :    
303 :     num = 0;
304 :     for (my = 0; my < (uint32_t)MBh; my++)
305 :     for (mx = 0; mx < (uint32_t)MBw; mx++)
306 :     {
307 :     const int mbnum = mx + my * MBw;
308 :     const VECTOR mv = pMBs[mbnum].mvs[0];
309 :    
310 :     if (!pMBs[mbnum].mcsel)
311 :     continue;
312 :    
313 :     if ( ( fabs(( sol[0] + (16*mx+8)*sol[1] + (16*my+8)*sol[2] ) - (double)mv.x ) > meanx )
314 :     || ( fabs(( sol[3] - (16*mx+8)*sol[2] + (16*my+8)*sol[1] ) - (double)mv.y ) > meany ) )
315 :     pMBs[mbnum].mcsel=0;
316 :     else
317 :     num++;
318 :     }
319 :    
320 :     } while ( (oldnum != num) && (num>= minblocks) );
321 :    
322 :     if (num < minblocks)
323 :     {
324 :     const int iEdgedWidth = pParam->edged_width;
325 :     num = 0;
326 :    
327 :     /* fprintf(stderr,"Warning! Unreliable GME (%d/%d blocks), falling back to translation.\n",num,MBh*MBw);
328 :     */
329 :     gmc.duv[0].x= gmc.duv[0].y= gmc.duv[1].x= gmc.duv[1].y= gmc.duv[2].x= gmc.duv[2].y=0;
330 :    
331 :     if (!(current->motion_flags & XVID_ME_GME_REFINE))
332 :     return gmc;
333 :    
334 :     for (my = 1; my < (uint32_t)MBh-1; my++) /* ignore boundary blocks */
335 :     for (mx = 1; mx < (uint32_t)MBw-1; mx++) /* theirs MVs are often wrong */
336 :     {
337 :     const int mbnum = mx + my * MBw;
338 :     MACROBLOCK *const pMB = &pMBs[mbnum];
339 :     const uint8_t *const pCur = current->image.y + 16*(my*iEdgedWidth + mx);
340 :     if ( (sad16 ( pCur, pCur+1 , iEdgedWidth, 65536) >= gradx )
341 :     && (sad16 ( pCur, pCur+iEdgedWidth, iEdgedWidth, 65536) >= grady ) )
342 :     { pMB->mcsel = 1;
343 :     gmc.duv[0].x += pMB->mvs[0].x;
344 :     gmc.duv[0].y += pMB->mvs[0].y;
345 :     num++;
346 :     }
347 :     }
348 :    
349 :     if (gmc.duv[0].x)
350 :     gmc.duv[0].x /= num;
351 :     if (gmc.duv[0].y)
352 :     gmc.duv[0].y /= num;
353 :     } else {
354 :    
355 :     gmc.duv[0].x=(int)(sol[0]+0.5);
356 :     gmc.duv[0].y=(int)(sol[3]+0.5);
357 :    
358 :     gmc.duv[1].x=(int)(sol[1]*pParam->width+0.5);
359 :     gmc.duv[1].y=(int)(-sol[2]*pParam->width+0.5);
360 :    
361 :     gmc.duv[2].x=-gmc.duv[1].y; /* two warp points only */
362 :     gmc.duv[2].y=gmc.duv[1].x;
363 :     }
364 :     if (num>maxblocks)
365 :     { for (my = 1; my < (uint32_t)MBh-1; my++)
366 :     for (mx = 1; mx < (uint32_t)MBw-1; mx++)
367 :     {
368 :     const int mbnum = mx + my * MBw;
369 :     if (pMBs[mbnum-1].mcsel)
370 :     pMBs[mbnum].mcsel=0;
371 :     else
372 :     if (pMBs[mbnum-MBw].mcsel)
373 :     pMBs[mbnum].mcsel=0;
374 :     }
375 :     }
376 :     return gmc;
377 :     }
378 :    
379 :     int
380 :     GlobalMotionEstRefine(
381 :     WARPPOINTS *const startwp,
382 :     MACROBLOCK * const pMBs,
383 :     const MBParam * const pParam,
384 :     const FRAMEINFO * const current,
385 :     const FRAMEINFO * const reference,
386 :     const IMAGE * const pCurr,
387 :     const IMAGE * const pRef,
388 :     const IMAGE * const pRefH,
389 :     const IMAGE * const pRefV,
390 :     const IMAGE * const pRefHV)
391 :     {
392 :     uint8_t* GMCblock = (uint8_t*)malloc(16*pParam->edged_width);
393 :     WARPPOINTS bestwp=*startwp;
394 :     WARPPOINTS centerwp,currwp;
395 :     int gmcminSAD=0;
396 :     int gmcSAD=0;
397 :     int direction;
398 :     #if 0
399 :     int mx,my;
400 :     #endif
401 :    
402 :     #if 0
403 :     /* use many blocks... */
404 :     for (my = 0; my < (uint32_t)pParam->mb_height; my++) {
405 :     for (mx = 0; mx < (uint32_t)pParam->mb_width; mx++) {
406 :     const int mbnum = mx + my * pParam->mb_width;
407 :     pMBs[mbnum].mcsel=1;
408 :     }
409 :     }
410 :     #endif
411 :    
412 :     #if 0
413 :     /* or rather don't use too many blocks... */
414 :     for (my = 1; my < (uint32_t)MBh-1; my++) {
415 :     for (mx = 1; mx < (uint32_t)MBw-1; mx++) {
416 :     const int mbnum = mx + my * MBw;
417 :     if (MBmask[mbnum-1])
418 :     MBmask[mbnum-1]=0;
419 :     else
420 :     if (MBmask[mbnum-MBw])
421 :     MBmask[mbnum-1]=0;
422 :    
423 :     }
424 :     }
425 :     #endif
426 :    
427 :     gmcminSAD = globalSAD(&bestwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
428 :    
429 :     if ( (reference->coding_type == S_VOP)
430 :     && ( (reference->warp.duv[1].x != bestwp.duv[1].x)
431 :     || (reference->warp.duv[1].y != bestwp.duv[1].y)
432 :     || (reference->warp.duv[0].x != bestwp.duv[0].x)
433 :     || (reference->warp.duv[0].y != bestwp.duv[0].y)
434 :     || (reference->warp.duv[2].x != bestwp.duv[2].x)
435 :     || (reference->warp.duv[2].y != bestwp.duv[2].y) ) )
436 :     {
437 :     gmcSAD = globalSAD(&reference->warp, pParam, pMBs,
438 :     current, pRef, pCurr, GMCblock);
439 :    
440 :     if (gmcSAD < gmcminSAD)
441 :     { bestwp = reference->warp;
442 :     gmcminSAD = gmcSAD;
443 :     }
444 :     }
445 :    
446 :     do {
447 :     direction = 0;
448 :     centerwp = bestwp;
449 :    
450 :     currwp = centerwp;
451 :    
452 :     currwp.duv[0].x--;
453 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
454 :     if (gmcSAD < gmcminSAD)
455 :     { bestwp = currwp;
456 :     gmcminSAD = gmcSAD;
457 :     direction = 1;
458 :     }
459 :     else
460 :     {
461 :     currwp = centerwp; currwp.duv[0].x++;
462 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
463 :     if (gmcSAD < gmcminSAD)
464 :     { bestwp = currwp;
465 :     gmcminSAD = gmcSAD;
466 :     direction = 2;
467 :     }
468 :     }
469 :     if (direction) continue;
470 :    
471 :     currwp = centerwp; currwp.duv[0].y--;
472 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
473 :     if (gmcSAD < gmcminSAD)
474 :     { bestwp = currwp;
475 :     gmcminSAD = gmcSAD;
476 :     direction = 4;
477 :     }
478 :     else
479 :     {
480 :     currwp = centerwp; currwp.duv[0].y++;
481 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
482 :     if (gmcSAD < gmcminSAD)
483 :     { bestwp = currwp;
484 :     gmcminSAD = gmcSAD;
485 :     direction = 8;
486 :     }
487 :     }
488 :     if (direction) continue;
489 :    
490 :     currwp = centerwp; currwp.duv[1].x++;
491 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
492 :     if (gmcSAD < gmcminSAD)
493 :     { bestwp = currwp;
494 :     gmcminSAD = gmcSAD;
495 :     direction = 32;
496 :     }
497 :     currwp.duv[2].y++;
498 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
499 :     if (gmcSAD < gmcminSAD)
500 :     { bestwp = currwp;
501 :     gmcminSAD = gmcSAD;
502 :     direction = 1024;
503 :     }
504 :    
505 :     currwp = centerwp; currwp.duv[1].x--;
506 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
507 :     if (gmcSAD < gmcminSAD)
508 :     { bestwp = currwp;
509 :     gmcminSAD = gmcSAD;
510 :     direction = 16;
511 :     }
512 :     else
513 :     {
514 :     currwp = centerwp; currwp.duv[1].x++;
515 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
516 :     if (gmcSAD < gmcminSAD)
517 :     { bestwp = currwp;
518 :     gmcminSAD = gmcSAD;
519 :     direction = 32;
520 :     }
521 :     }
522 :     if (direction) continue;
523 :    
524 :    
525 :     currwp = centerwp; currwp.duv[1].y--;
526 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
527 :     if (gmcSAD < gmcminSAD)
528 :     { bestwp = currwp;
529 :     gmcminSAD = gmcSAD;
530 :     direction = 64;
531 :     }
532 :     else
533 :     {
534 :     currwp = centerwp; currwp.duv[1].y++;
535 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
536 :     if (gmcSAD < gmcminSAD)
537 :     { bestwp = currwp;
538 :     gmcminSAD = gmcSAD;
539 :     direction = 128;
540 :     }
541 :     }
542 :     if (direction) continue;
543 :    
544 :     currwp = centerwp; currwp.duv[2].x--;
545 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
546 :     if (gmcSAD < gmcminSAD)
547 :     { bestwp = currwp;
548 :     gmcminSAD = gmcSAD;
549 :     direction = 256;
550 :     }
551 :     else
552 :     {
553 :     currwp = centerwp; currwp.duv[2].x++;
554 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
555 :     if (gmcSAD < gmcminSAD)
556 :     { bestwp = currwp;
557 :     gmcminSAD = gmcSAD;
558 :     direction = 512;
559 :     }
560 :     }
561 :     if (direction) continue;
562 :    
563 :     currwp = centerwp; currwp.duv[2].y--;
564 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
565 :     if (gmcSAD < gmcminSAD)
566 :     { bestwp = currwp;
567 :     gmcminSAD = gmcSAD;
568 :     direction = 1024;
569 :     }
570 :     else
571 :     {
572 :     currwp = centerwp; currwp.duv[2].y++;
573 :     gmcSAD = globalSAD(&currwp, pParam, pMBs, current, pRef, pCurr, GMCblock);
574 :     if (gmcSAD < gmcminSAD)
575 :     { bestwp = currwp;
576 :     gmcminSAD = gmcSAD;
577 :     direction = 2048;
578 :     }
579 :     }
580 :     } while (direction);
581 :     free(GMCblock);
582 :    
583 :     *startwp = bestwp;
584 :    
585 :     return gmcminSAD;
586 :     }
587 :    
588 :     int
589 :     globalSAD(const WARPPOINTS *const wp,
590 :     const MBParam * const pParam,
591 :     const MACROBLOCK * const pMBs,
592 :     const FRAMEINFO * const current,
593 :     const IMAGE * const pRef,
594 :     const IMAGE * const pCurr,
595 :     uint8_t *const GMCblock)
596 :     {
597 :     NEW_GMC_DATA gmc_data;
598 :     int iSAD, gmcSAD=0;
599 :     int num=0;
600 :     unsigned int mx, my;
601 :    
602 :     generate_GMCparameters( 3, 3, wp, pParam->width, pParam->height, &gmc_data);
603 :    
604 :     for (my = 0; my < (uint32_t)pParam->mb_height; my++)
605 :     for (mx = 0; mx < (uint32_t)pParam->mb_width; mx++) {
606 :    
607 :     const int mbnum = mx + my * pParam->mb_width;
608 :     const int iEdgedWidth = pParam->edged_width;
609 :    
610 :     if (!pMBs[mbnum].mcsel)
611 :     continue;
612 :    
613 :     gmc_data.predict_16x16(&gmc_data, GMCblock,
614 :     pRef->y,
615 :     iEdgedWidth,
616 :     iEdgedWidth,
617 :     mx, my,
618 :     pParam->m_rounding_type);
619 :    
620 :     iSAD = sad16 ( pCurr->y + 16*(my*iEdgedWidth + mx),
621 :     GMCblock , iEdgedWidth, 65536);
622 :     iSAD -= pMBs[mbnum].sad16;
623 :    
624 :     if (iSAD<0)
625 :     gmcSAD += iSAD;
626 :     num++;
627 :     }
628 :     return gmcSAD;
629 :     }

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