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

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

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