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

Diff of /xvidcore/src/motion/estimation_gmc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1, Wed Sep 10 22:18:59 2003 UTC revision 1.1.2.2, Tue Sep 30 18:20:31 2003 UTC
# Line 0  Line 1 
1    /*****************************************************************************
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     * $Id$
23     *
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, const 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                                    SearchData * const Data)
72    {
73    
74            MACROBLOCK * const pMB = &pMBs[x + y * pParam->mb_width];
75    
76            Data->iMinSAD[0] = MV_MAX_ERROR;
77    
78            Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
79    
80            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
81                                    pParam->width, pParam->height, 16, 1, 0);
82    
83            Data->Cur = pCur + 16*(x + y * pParam->edged_width);
84            Data->RefP[0] = pRef + 16*(x + y * pParam->edged_width);
85            Data->RefP[1] = pRefV + 16*(x + y * pParam->edged_width);
86            Data->RefP[2] = pRefH + 16*(x + y * pParam->edged_width);
87            Data->RefP[3] = pRefHV + 16*(x + y * pParam->edged_width);
88    
89            Data->currentMV[0].x = Data->currentMV[0].y = 0;
90            CheckCandidate16I(0, 0, Data, 255);
91    
92            if ( (Data->predMV.x !=0) || (Data->predMV.y != 0) )
93                    CheckCandidate16I(Data->predMV.x, Data->predMV.y, Data, 255);
94    
95            xvid_me_DiamondSearch(Data->currentMV[0].x, Data->currentMV[0].y, Data, 255, CheckCandidate16I);
96    
97            xvid_me_SubpelRefine(Data, CheckCandidate16I);
98    
99    
100            /* for QPel halfpel positions are worse than in halfpel mode :( */
101    /*      if (Data->qpel) {
102                    Data->currentQMV->x = 2*Data->currentMV->x;
103                    Data->currentQMV->y = 2*Data->currentMV->y;
104                    Data->qpel_precision = 1;
105                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
106                                            pParam->width, pParam->height, iFcode, 2, 0);
107                    SubpelRefine(Data);
108            }
109    */
110    
111            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
112            pMB->sad16 = Data->iMinSAD[0];
113            pMB->mode = MODE_INTER;
114            pMB->sad16 += 10*d_mv_bits(pMB->mvs[0].x, pMB->mvs[0].y, Data->predMV, Data->iFcode, 0, 0);
115            return;
116    }
117    
118    
119    void
120    GMEanalysis(const MBParam * const pParam,
121                            const FRAMEINFO * const current,
122                            const FRAMEINFO * const reference,
123                            const IMAGE * const pRefH,
124                            const IMAGE * const pRefV,
125                            const IMAGE * const pRefHV)
126    {
127            uint32_t x, y;
128            MACROBLOCK * const pMBs = current->mbs;
129            const IMAGE * const pCurrent = &current->image;
130            const IMAGE * const pReference = &reference->image;
131    
132            int32_t iMinSAD[5], temp[5];
133            VECTOR currentMV[5];
134            uint32_t dir;
135            SearchData Data;
136            memset(&Data, 0, sizeof(SearchData));
137    
138            Data.iEdgedWidth = pParam->edged_width;
139            Data.rounding = pParam->m_rounding_type;
140    
141            Data.currentMV = &currentMV[0];
142            Data.iMinSAD = &iMinSAD[0];
143            Data.iFcode = current->fcode;
144            Data.temp = temp;
145            Data.dir = &dir;
146    
147            if (sadInit) (*sadInit) ();
148    
149            for (y = 0; y < pParam->mb_height; y ++) {
150                    for (x = 0; x < pParam->mb_width; x ++) {
151                            GMEanalyzeMB(pCurrent->y, pReference->y, pRefH->y, pRefV->y, pRefHV->y, x, y, pParam, pMBs, &Data);
152                    }
153            }
154            return;
155    }
156    
157    WARPPOINTS
158    GlobalMotionEst(MACROBLOCK * const pMBs,
159                                    const MBParam * const pParam,
160                                    const FRAMEINFO * const current,
161                                    const FRAMEINFO * const reference,
162                                    const IMAGE * const pRefH,
163                                    const IMAGE * const pRefV,
164                                    const IMAGE * const pRefHV)
165    {
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            GMEanalysis(pParam,current, reference, pRefH, pRefV, pRefHV);
189    
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    }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.2.2

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