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

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

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