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

Diff of /xvidcore/src/motion/estimation_common.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     *  - Motion Estimation shared functions -
5     *
6     *  Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7     *               2002 Michael Militzer <michael@xvid.org>
8     *               2002-2003 Radoslaw Czyz <xvid@syskin.cjb.net>
9     *
10     *  This program is free software ; you can redistribute it and/or modify
11     *  it under the terms of the GNU General Public License as published by
12     *  the Free Software Foundation ; either version 2 of the License, or
13     *  (at your option) any later version.
14     *
15     *  This program is distributed in the hope that it will be useful,
16     *  but WITHOUT ANY WARRANTY ; without even the implied warranty of
17     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     *  GNU General Public License for more details.
19     *
20     *  You should have received a copy of the GNU General Public License
21     *  along with this program ; if not, write to the Free Software
22     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23     *
24     * $Id$
25     *
26     ****************************************************************************/
27    
28    #include "../encoder.h"
29    #include "../global.h"
30    #include "../image/interpolate8x8.h"
31    #include "estimation.h"
32    #include "motion.h"
33    #include "sad.h"
34    #include "motion_inlines.h"
35    
36    
37    /*****************************************************************************
38     * Modified rounding tables
39     * Original tables see ISO spec tables 7-6 -> 7-9
40     ****************************************************************************/
41    
42    const uint32_t roundtab[16] =
43    {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2 };
44    
45    /* K = 4 */
46    const uint32_t roundtab_76[16] =
47    { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };
48    
49    /* K = 2 */
50    const uint32_t roundtab_78[8] =
51    { 0, 0, 1, 1, 0, 0, 0, 1  };
52    
53    /* K = 1 */
54    const uint32_t roundtab_79[4] =
55    { 0, 1, 0, 0 };
56    
57    const int xvid_me_lambda_vec16[32] =
58            {     0    ,(int)(1.00235 * NEIGH_TEND_16X16 + 0.5),
59            (int)(1.15582*NEIGH_TEND_16X16 + 0.5), (int)(1.31976*NEIGH_TEND_16X16 + 0.5),
60            (int)(1.49591*NEIGH_TEND_16X16 + 0.5), (int)(1.68601*NEIGH_TEND_16X16 + 0.5),
61            (int)(1.89187*NEIGH_TEND_16X16 + 0.5), (int)(2.11542*NEIGH_TEND_16X16 + 0.5),
62            (int)(2.35878*NEIGH_TEND_16X16 + 0.5), (int)(2.62429*NEIGH_TEND_16X16 + 0.5),
63            (int)(2.91455*NEIGH_TEND_16X16 + 0.5), (int)(3.23253*NEIGH_TEND_16X16 + 0.5),
64            (int)(3.58158*NEIGH_TEND_16X16 + 0.5), (int)(3.96555*NEIGH_TEND_16X16 + 0.5),
65            (int)(4.38887*NEIGH_TEND_16X16 + 0.5), (int)(4.85673*NEIGH_TEND_16X16 + 0.5),
66            (int)(5.37519*NEIGH_TEND_16X16 + 0.5), (int)(5.95144*NEIGH_TEND_16X16 + 0.5),
67            (int)(6.59408*NEIGH_TEND_16X16 + 0.5), (int)(7.31349*NEIGH_TEND_16X16 + 0.5),
68            (int)(8.12242*NEIGH_TEND_16X16 + 0.5), (int)(9.03669*NEIGH_TEND_16X16 + 0.5),
69            (int)(10.0763*NEIGH_TEND_16X16 + 0.5), (int)(11.2669*NEIGH_TEND_16X16 + 0.5),
70            (int)(12.6426*NEIGH_TEND_16X16 + 0.5), (int)(14.2493*NEIGH_TEND_16X16 + 0.5),
71            (int)(16.1512*NEIGH_TEND_16X16 + 0.5), (int)(18.442*NEIGH_TEND_16X16 + 0.5),
72            (int)(21.2656*NEIGH_TEND_16X16 + 0.5), (int)(24.8580*NEIGH_TEND_16X16 + 0.5),
73            (int)(29.6436*NEIGH_TEND_16X16 + 0.5), (int)(36.4949*NEIGH_TEND_16X16 + 0.5)
74    };
75    
76    /*****************************************************************************
77     * Code
78     ****************************************************************************/
79    
80    int32_t
81    xvid_me_ChromaSAD(const int dx, const int dy, SearchData * const data)
82    {
83            int sad;
84            const uint32_t stride = data->iEdgedWidth/2;
85            int offset = (dx>>1) + (dy>>1)*stride;
86            int next = 1;
87    
88            if (dx == data->chromaX && dy == data->chromaY)
89                    return data->chromaSAD; /* it has been checked recently */
90            data->chromaX = dx; data->chromaY = dy; /* backup */
91    
92            switch (((dx & 1) << 1) | (dy & 1))     {
93                    case 0:
94                            sad = sad8(data->CurU, data->RefP[4] + offset, stride);
95                            sad += sad8(data->CurV, data->RefP[5] + offset, stride);
96                            break;
97                    case 1:
98                            next = stride;
99                    case 2:
100                            sad = sad8bi(data->CurU, data->RefP[4] + offset, data->RefP[4] + offset + next, stride);
101                            sad += sad8bi(data->CurV, data->RefP[5] + offset, data->RefP[5] + offset + next, stride);
102                            break;
103                    default:
104                            interpolate8x8_halfpel_hv(data->RefQ, data->RefP[4] + offset, stride, data->rounding);
105                            sad = sad8(data->CurU, data->RefQ, stride);
106    
107                            interpolate8x8_halfpel_hv(data->RefQ, data->RefP[5] + offset, stride, data->rounding);
108                            sad += sad8(data->CurV, data->RefQ, stride);
109                            break;
110            }
111            data->chromaSAD = sad; /* backup, part 2 */
112            return sad;
113    }
114    
115    uint8_t *
116    xvid_me_interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
117    {
118            /* create or find a qpel-precision reference picture; return pointer to it */
119            uint8_t * Reference = data->RefQ + 16*dir;
120            const uint32_t iEdgedWidth = data->iEdgedWidth;
121            const uint32_t rounding = data->rounding;
122            const int halfpel_x = x/2;
123            const int halfpel_y = y/2;
124            const uint8_t *ref1, *ref2, *ref3, *ref4;
125    
126            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
127            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
128            switch( ((x&1)<<1) + (y&1) ) {
129            case 3: /* x and y in qpel resolution - the "corners" (top left/right and */
130                            /* bottom left/right) during qpel refinement */
131                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
132                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
133                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
134                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
135                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
136                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
137                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
138                    break;
139    
140            case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
141                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
142                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
143                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
144                    break;
145    
146            case 2: /* x qpel, y halfpel - left or right during qpel refinement */
147                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
148                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
149                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
150                    break;
151    
152            default: /* pure halfpel position */
153                    return (uint8_t *) ref1;
154    
155            }
156            return Reference;
157    }
158    
159    uint8_t *
160    xvid_me_interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
161    {
162            /* create or find a qpel-precision reference picture; return pointer to it */
163            uint8_t * Reference = data->RefQ + 16*dir;
164            const uint32_t iEdgedWidth = data->iEdgedWidth;
165            const uint32_t rounding = data->rounding;
166            const int halfpel_x = x/2;
167            const int halfpel_y = y/2;
168            const uint8_t *ref1, *ref2, *ref3, *ref4;
169    
170            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
171            switch( ((x&1)<<1) + (y&1) ) {
172            case 3:
173                    /*
174                     * x and y in qpel resolution - the "corners" (top left/right and
175                     * bottom left/right) during qpel refinement
176                     */
177                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
178                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
179                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
180                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
181                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
182                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
183                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
184                    break;
185    
186            case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
187                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
188                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
189                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
190                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
191                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
192                    break;
193    
194            case 2: /* x qpel, y halfpel - left or right during qpel refinement */
195                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
196                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
197                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
198                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
199                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
200                    break;
201    
202    
203            default: /* pure halfpel position */
204                    return (uint8_t *) ref1;
205            }
206            return Reference;
207    }
208    
209    void
210    xvid_me_AdvDiamondSearch(int x, int y, SearchData * const data,
211                                                     int bDirection, CheckFunc * const CheckCandidate)
212    {
213    
214    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
215    
216            unsigned int * const iDirection = &data->dir;
217    
218            for(;;) { /* forever */
219                    *iDirection = 0;
220                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
221                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
222                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
223                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
224    
225                    /* now we're doing diagonal checks near our candidate */
226    
227                    if (*iDirection) {              /* if anything found */
228                            bDirection = *iDirection;
229                            *iDirection = 0;
230                            x = data->currentMV->x; y = data->currentMV->y;
231                            if (bDirection & 3) {   /* our candidate is left or right */
232                                    CHECK_CANDIDATE(x, y + iDiamondSize, 8);
233                                    CHECK_CANDIDATE(x, y - iDiamondSize, 4);
234                            } else {                        /* what remains here is up or down */
235                                    CHECK_CANDIDATE(x + iDiamondSize, y, 2);
236                                    CHECK_CANDIDATE(x - iDiamondSize, y, 1);
237                            }
238    
239                            if (*iDirection) {
240                                    bDirection += *iDirection;
241                                    x = data->currentMV->x; y = data->currentMV->y;
242                            }
243                    } else {                                /* about to quit, eh? not so fast.... */
244                            switch (bDirection) {
245                            case 2:
246                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
247                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
248                                    break;
249                            case 1:
250                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
251                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
252                                    break;
253                            case 2 + 4:
254                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
255                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
256                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
257                                    break;
258                            case 4:
259                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
260                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
261                                    break;
262                            case 8:
263                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
264                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
265                                    break;
266                            case 1 + 4:
267                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
268                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
269                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
270                                    break;
271                            case 2 + 8:
272                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
273                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
274                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
275                                    break;
276                            case 1 + 8:
277                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
278                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
279                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
280                                    break;
281                            default:                /* 1+2+4+8 == we didn't find anything at all */
282                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
283                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
284                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
285                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
286                                    break;
287                            }
288                            if (!*iDirection) break;                /* ok, the end. really */
289                            bDirection = *iDirection;
290                            x = data->currentMV->x; y = data->currentMV->y;
291                    }
292            }
293    }
294    
295    void
296    xvid_me_SquareSearch(int x, int y, SearchData * const data,
297                                             int bDirection, CheckFunc * const CheckCandidate)
298    {
299            unsigned int * const iDirection = &data->dir;
300    
301            do {
302                    *iDirection = 0;
303                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1+16+64);
304                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2+32+128);
305                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4+16+32);
306                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8+64+128);
307                    if (bDirection & 16) CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1+4+16+32+64);
308                    if (bDirection & 32) CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2+4+16+32+128);
309                    if (bDirection & 64) CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1+8+16+64+128);
310                    if (bDirection & 128) CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2+8+32+64+128);
311    
312                    bDirection = *iDirection;
313                    x = data->currentMV->x; y = data->currentMV->y;
314            } while (*iDirection);
315    }
316    
317    void
318    xvid_me_DiamondSearch(int x, int y, SearchData * const data,
319                                              int bDirection, CheckFunc * const CheckCandidate)
320    {
321    
322    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
323    
324            unsigned int * const iDirection = &data->dir;
325    
326            do {
327                    *iDirection = 0;
328                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
329                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
330                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
331                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
332    
333                    /* now we're doing diagonal checks near our candidate */
334    
335                    if (*iDirection) {              /* checking if anything found */
336                            bDirection = *iDirection;
337                            *iDirection = 0;
338                            x = data->currentMV->x; y = data->currentMV->y;
339                            if (bDirection & 3) {   /* our candidate is left or right */
340                                    CHECK_CANDIDATE(x, y + iDiamondSize, 8);
341                                    CHECK_CANDIDATE(x, y - iDiamondSize, 4);
342                            } else {                        /* what remains here is up or down */
343                                    CHECK_CANDIDATE(x + iDiamondSize, y, 2);
344                                    CHECK_CANDIDATE(x - iDiamondSize, y, 1);
345                            }
346                            bDirection += *iDirection;
347                            x = data->currentMV->x; y = data->currentMV->y;
348                    }
349            }
350            while (*iDirection);
351    }
352    
353    void
354    xvid_me_SubpelRefine(SearchData * const data, CheckFunc * const CheckCandidate)
355    {
356    /* Do a half-pel or q-pel refinement */
357            const VECTOR centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
358    
359            CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, 0);
360            CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, 0);
361            CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, 0);
362            CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, 0);
363            CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, 0);
364            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, 0);
365            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, 0);
366            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y - 1, 0);
367    }
368    
369    void
370    SubpelRefine_Fast(SearchData * data, CheckFunc * CheckCandidate)
371    {
372    /* Do a fast q-pel refinement */
373            VECTOR centerMV;
374            VECTOR second_best;
375            int best_sad = *data->iMinSAD;
376            int xo, yo, xo2, yo2;
377            int size = 2;
378            data->iMinSAD2 = 0;
379    
380            /* check all halfpixel positions near our best halfpel position */
381            centerMV = *data->currentQMV;
382            *data->iMinSAD = 256 * 4096;
383    
384            CHECK_CANDIDATE(centerMV.x, centerMV.y - size, 0);
385            CHECK_CANDIDATE(centerMV.x + size, centerMV.y - size, 0);
386            CHECK_CANDIDATE(centerMV.x + size, centerMV.y, 0);
387            CHECK_CANDIDATE(centerMV.x + size, centerMV.y + size, 0);
388    
389            CHECK_CANDIDATE(centerMV.x, centerMV.y + size, 0);
390            CHECK_CANDIDATE(centerMV.x - size, centerMV.y + size, 0);
391            CHECK_CANDIDATE(centerMV.x - size, centerMV.y, 0);
392            CHECK_CANDIDATE(centerMV.x - size, centerMV.y - size, 0);
393    
394            second_best = *data->currentQMV;
395    
396            /* after second_best has been found, go back to the vector we began with */
397    
398            data->currentQMV[0] = centerMV;
399            *data->iMinSAD = best_sad;
400    
401            xo = centerMV.x;
402            yo = centerMV.y;
403            xo2 = second_best.x;
404            yo2 = second_best.y;
405    
406            data->iMinSAD2 = 256 * 4096;
407    
408            if (yo == yo2) {
409                    CHECK_CANDIDATE((xo+xo2)>>1, yo, 0);
410                    CHECK_CANDIDATE(xo, yo-1, 0);
411                    CHECK_CANDIDATE(xo, yo+1, 0);
412    
413                    if(best_sad <= data->iMinSAD2) return;
414    
415                    if(data->currentQMV[0].x == data->currentQMV2.x) {
416                            CHECK_CANDIDATE((xo+xo2)>>1, yo-1, 0);
417                            CHECK_CANDIDATE((xo+xo2)>>1, yo+1, 0);
418                    } else {
419                            CHECK_CANDIDATE((xo+xo2)>>1,
420                                    (data->currentQMV[0].x == xo) ? data->currentQMV[0].y : data->currentQMV2.y, 0);
421                    }
422                    return;
423            }
424    
425            if (xo == xo2) {
426                    CHECK_CANDIDATE(xo, (yo+yo2)>>1, 0);
427                    CHECK_CANDIDATE(xo-1, yo, 0);
428                    CHECK_CANDIDATE(xo+1, yo, 0);
429    
430                    if(best_sad < data->iMinSAD2) return;
431    
432                    if(data->currentQMV[0].y == data->currentQMV2.y) {
433                            CHECK_CANDIDATE(xo-1, (yo+yo2)>>1, 0);
434                            CHECK_CANDIDATE(xo+1, (yo+yo2)>>1, 0);
435                    } else {
436                            CHECK_CANDIDATE((data->currentQMV[0].y == yo) ? data->currentQMV[0].x : data->currentQMV2.x, (yo+yo2)>>1, 0);
437                    }
438                    return;
439            }
440    
441            CHECK_CANDIDATE(xo, (yo+yo2)>>1, 0);
442            CHECK_CANDIDATE((xo+xo2)>>1, yo, 0);
443    
444            if(best_sad <= data->iMinSAD2) return;
445    
446            CHECK_CANDIDATE((xo+xo2)>>1, (yo+yo2)>>1, 0);
447    }

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