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

Diff of /xvidcore/src/motion/estimation_pvop.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     *  - Motion Estimation for P- and S- VOPs  -
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 <assert.h>
29    #include <stdio.h>
30    #include <stdlib.h>
31    #include <string.h>     /* memcpy */
32    
33    #include "../encoder.h"
34    #include "../prediction/mbprediction.h"
35    #include "../global.h"
36    #include "../utils/timer.h"
37    #include "../image/interpolate8x8.h"
38    #include "estimation.h"
39    #include "motion.h"
40    #include "sad.h"
41    #include "motion_inlines.h"
42    
43    static const int xvid_me_lambda_vec8[32] =
44            {     0    ,(int)(1.00235 * NEIGH_TEND_8X8 + 0.5),
45            (int)(1.15582 + NEIGH_TEND_8X8 + 0.5), (int)(1.31976*NEIGH_TEND_8X8 + 0.5),
46            (int)(1.49591*NEIGH_TEND_8X8 + 0.5), (int)(1.68601*NEIGH_TEND_8X8 + 0.5),
47            (int)(1.89187*NEIGH_TEND_8X8 + 0.5), (int)(2.11542*NEIGH_TEND_8X8 + 0.5),
48            (int)(2.35878*NEIGH_TEND_8X8 + 0.5), (int)(2.62429*NEIGH_TEND_8X8 + 0.5),
49            (int)(2.91455*NEIGH_TEND_8X8 + 0.5), (int)(3.23253*NEIGH_TEND_8X8 + 0.5),
50            (int)(3.58158*NEIGH_TEND_8X8 + 0.5), (int)(3.96555*NEIGH_TEND_8X8 + 0.5),
51            (int)(4.38887*NEIGH_TEND_8X8 + 0.5), (int)(4.85673*NEIGH_TEND_8X8 + 0.5),
52            (int)(5.37519*NEIGH_TEND_8X8 + 0.5), (int)(5.95144*NEIGH_TEND_8X8 + 0.5),
53            (int)(6.59408*NEIGH_TEND_8X8 + 0.5), (int)(7.31349*NEIGH_TEND_8X8 + 0.5),
54            (int)(8.12242*NEIGH_TEND_8X8 + 0.5), (int)(9.03669*NEIGH_TEND_8X8 + 0.5),
55            (int)(10.0763*NEIGH_TEND_8X8 + 0.5), (int)(11.2669*NEIGH_TEND_8X8 + 0.5),
56            (int)(12.6426*NEIGH_TEND_8X8 + 0.5), (int)(14.2493*NEIGH_TEND_8X8 + 0.5),
57            (int)(16.1512*NEIGH_TEND_8X8 + 0.5), (int)(18.442*NEIGH_TEND_8X8 + 0.5),
58            (int)(21.2656*NEIGH_TEND_8X8 + 0.5), (int)(24.8580*NEIGH_TEND_8X8 + 0.5),
59            (int)(29.6436*NEIGH_TEND_8X8 + 0.5), (int)(36.4949*NEIGH_TEND_8X8 + 0.5)
60    };
61    
62    static void
63    CheckCandidate16(const int x, const int y, const SearchData * const data, const unsigned int Direction)
64    {
65            int xc, yc;
66            const uint8_t * Reference;
67            VECTOR * current;
68            int32_t sad; uint32_t t;
69    
70            if ( (x > data->max_dx) || (x < data->min_dx)
71                    || (y > data->max_dy) || (y < data->min_dy) ) return;
72    
73            if (!data->qpel_precision) {
74                    Reference = GetReference(x, y, data);
75                    current = data->currentMV;
76                    xc = x; yc = y;
77            } else { /* x and y are in 1/4 precision */
78                    Reference = xvid_me_interpolate16x16qpel(x, y, 0, data);
79                    xc = x/2; yc = y/2; /* for chroma sad */
80                    current = data->currentQMV;
81            }
82    
83            sad = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp);
84            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
85    
86            sad += (data->lambda16 * t * sad)>>10;
87            data->temp[0] += (data->lambda8 * t * (data->temp[0] + NEIGH_8X8_BIAS))>>10;
88    
89            if (data->chroma && sad < data->iMinSAD[0])
90                    sad += xvid_me_ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
91                                                                    (yc >> 1) + roundtab_79[yc & 0x3], data);
92    
93            if (sad < data->iMinSAD[0]) {
94                    data->iMinSAD[0] = sad;
95                    current[0].x = x; current[0].y = y;
96                    *data->dir = Direction;
97            }
98    
99            if (data->temp[0] < data->iMinSAD[1]) {
100                    data->iMinSAD[1] = data->temp[0]; current[1].x = x; current[1].y = y; }
101            if (data->temp[1] < data->iMinSAD[2]) {
102                    data->iMinSAD[2] = data->temp[1]; current[2].x = x; current[2].y = y; }
103            if (data->temp[2] < data->iMinSAD[3]) {
104                    data->iMinSAD[3] = data->temp[2]; current[3].x = x; current[3].y = y; }
105            if (data->temp[3] < data->iMinSAD[4]) {
106                    data->iMinSAD[4] = data->temp[3]; current[4].x = x; current[4].y = y; }
107    }
108    
109    static void
110    CheckCandidate16_subpel(const int x, const int y, const SearchData * const data, const unsigned int Direction)
111    {
112            int xc, yc;
113            const uint8_t *Reference;
114            VECTOR *current, *current2;
115            int32_t sad; uint32_t t;
116    
117            if ( (x > data->max_dx) || (x < data->min_dx)
118                    || (y > data->max_dy) || (y < data->min_dy) ) return;
119    
120            if (!data->qpel_precision) {
121                    Reference = GetReference(x, y, data);
122                    current = data->currentMV;
123                    current2 = data->currentMV2;
124                    xc = x; yc = y;
125            } else { /* x and y are in 1/4 precision */
126                    Reference = xvid_me_interpolate16x16qpel(x, y, 0, data);
127                    xc = x/2; yc = y/2; /* for chroma sad */
128                    current = data->currentQMV;
129                    current2 = data->currentQMV2;
130            }
131    
132            sad = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp);
133            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
134    
135            sad += (data->lambda16 * t * sad)>>10;
136            data->temp[0] += (data->lambda8 * t * (data->temp[0] + NEIGH_8X8_BIAS))>>10;
137    
138            if (data->chroma && sad < data->iMinSAD[0])
139                    sad += xvid_me_ChromaSAD((xc >> 1) + roundtab_79[xc & 0x3],
140                                                                    (yc >> 1) + roundtab_79[yc & 0x3], data);
141    
142            if (data->temp[0] < data->iMinSAD[1]) {
143                    data->iMinSAD[1] = data->temp[0]; current[1].x = x; current[1].y = y; }
144            if (data->temp[1] < data->iMinSAD[2]) {
145                    data->iMinSAD[2] = data->temp[1]; current[2].x = x; current[2].y = y; }
146            if (data->temp[2] < data->iMinSAD[3]) {
147                    data->iMinSAD[3] = data->temp[2]; current[3].x = x; current[3].y = y; }
148            if (data->temp[3] < data->iMinSAD[4]) {
149                    data->iMinSAD[4] = data->temp[3]; current[4].x = x; current[4].y = y; }
150    
151            if (sad < data->iMinSAD[0]) {
152                    *(data->iMinSAD2) = *(data->iMinSAD);
153                    current2->x = current->x; current2->y = current->y;
154    
155                    data->iMinSAD[0] = sad;
156                    current[0].x = x; current[0].y = y;
157                    *data->dir = Direction;
158                    return;
159            }
160    
161            if (sad < *(data->iMinSAD2)) {
162                    *(data->iMinSAD2) = sad;
163                    current2->x = x; current2->y = y;
164                    *data->dir = Direction;
165            }
166    }
167    
168    static void
169    CheckCandidate8(const int x, const int y, const SearchData * const data, const unsigned int Direction)
170    {
171            int32_t sad; uint32_t t;
172            const uint8_t * Reference;
173            VECTOR * current;
174    
175            if ( (x > data->max_dx) || (x < data->min_dx)
176                    || (y > data->max_dy) || (y < data->min_dy) ) return;
177    
178            if (!data->qpel_precision) {
179                    Reference = GetReference(x, y, data);
180                    current = data->currentMV;
181            } else { /* x and y are in 1/4 precision */
182                    Reference = xvid_me_interpolate8x8qpel(x, y, 0, 0, data);
183                    current = data->currentQMV;
184            }
185    
186            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
187            t = d_mv_bits(x, y, data->predMV, data->iFcode, data->qpel^data->qpel_precision, 0);
188    
189            sad += (data->lambda8 * t * (sad+NEIGH_8X8_BIAS))>>10;
190    
191            if (sad < *(data->iMinSAD)) {
192                    *(data->iMinSAD) = sad;
193                    current->x = x; current->y = y;
194                    *data->dir = Direction;
195            }
196    }
197    
198    static void
199    CheckCandidate32(const int x, const int y, const SearchData * const data, const unsigned int Direction)
200    {
201            uint32_t t;
202            const uint8_t * Reference;
203            int sad;
204    
205            if ( (!(x&1) && x !=0) || (!(y&1) && y !=0) || /* non-zero even value */
206                    (x > data->max_dx) || (x < data->min_dx)
207                    || (y > data->max_dy) || (y < data->min_dy) ) return;
208    
209            Reference = GetReference(x, y, data);
210            t = d_mv_bits(x, y, data->predMV, data->iFcode, 0, 1);
211    
212            sad = sad32v_c(data->Cur, Reference, data->iEdgedWidth, data->temp);
213    
214            sad += (data->lambda16 * t * sad) >> 10;
215            data->temp[0] += (data->lambda8 * t * (data->temp[0] + NEIGH_8X8_BIAS))>>10;
216    
217            if (sad < data->iMinSAD[0]) {
218                    data->iMinSAD[0] = sad;
219                    data->currentMV[0].x = x; data->currentMV[0].y = y;
220                    *data->dir = Direction;
221            }
222    
223            if (data->temp[0] < data->iMinSAD[1]) {
224                    data->iMinSAD[1] = data->temp[0]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
225            if (data->temp[1] < data->iMinSAD[2]) {
226                    data->iMinSAD[2] = data->temp[1]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
227            if (data->temp[2] < data->iMinSAD[3]) {
228                    data->iMinSAD[3] = data->temp[2]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
229            if (data->temp[3] < data->iMinSAD[4]) {
230                    data->iMinSAD[4] = data->temp[3]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
231    }
232    
233    static void
234    SubpelRefine_Fast(SearchData * data, CheckFunc * CheckCandidate)
235    {
236    /* Do a half-pel or q-pel refinement */
237            VECTOR centerMV;
238            VECTOR second_best;
239            int best_sad = *data->iMinSAD;
240            int xo, yo, xo2, yo2;
241            int size = 2;
242            CheckFunc *backupFunc = CheckCandidate;
243    
244            if(data->qpel_precision)
245                    size = 1;
246    
247            centerMV = *data->currentMV;
248            *data->iMinSAD = 256 * 4096;
249    
250            CHECK_CANDIDATE(centerMV.x, centerMV.y - size, 0);
251            CHECK_CANDIDATE(centerMV.x + size, centerMV.y - size, 0);
252            CHECK_CANDIDATE(centerMV.x + size, centerMV.y, 0);
253            CHECK_CANDIDATE(centerMV.x + size, centerMV.y + size, 0);
254    
255            CHECK_CANDIDATE(centerMV.x, centerMV.y + size, 0);
256            CHECK_CANDIDATE(centerMV.x - size, centerMV.y + size, 0);
257            CHECK_CANDIDATE(centerMV.x - size, centerMV.y, 0);
258            CHECK_CANDIDATE(centerMV.x - size, centerMV.y - size, 0);
259    
260            second_best = *data->currentMV;
261    
262            if(data->qpel_precision) {
263                    second_best.x *= 2;     second_best.y *= 2;
264            }
265    
266            data->currentMV[0] = centerMV;
267            *data->iMinSAD = best_sad;
268    
269        centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
270    
271            xo = centerMV.x;
272            yo = centerMV.y;
273            xo2 = second_best.x;
274            yo2 = second_best.y;
275    
276            CheckCandidate = CheckCandidate16_subpel;
277            *data->iMinSAD2 = 256 * 4096;
278    
279            if (yo == yo2)
280            {
281                    CHECK_CANDIDATE((xo+xo2)>>1, yo, 0);
282                    CHECK_CANDIDATE(xo, yo-1, 0);
283                    CHECK_CANDIDATE(xo, yo+1, 0);
284    
285                    if(best_sad <= *data->iMinSAD2)
286                            goto ende;
287    
288                    if(data->currentQMV[0].x == data->currentQMV2[0].x) {
289                            CHECK_CANDIDATE((xo+xo2)>>1, yo-1, 0);
290                            CHECK_CANDIDATE((xo+xo2)>>1, yo+1, 0);
291                            goto ende;
292                    }
293                    else {
294                            CHECK_CANDIDATE((xo+xo2)>>1,
295                                    (data->currentQMV[0].x == xo) ? data->currentQMV[0].y : data->currentQMV2[0].y,
296                                    0);
297                            goto ende;
298                    }
299            }
300    
301            if (xo == xo2)
302            {
303                    CHECK_CANDIDATE(xo, (yo+yo2)>>1, 0);
304                    CHECK_CANDIDATE(xo-1, yo, 0);
305                    CHECK_CANDIDATE(xo+1, yo, 0);
306    
307                    if(best_sad < *data->iMinSAD2)
308                            goto ende;
309    
310                    if(data->currentQMV[0].y == data->currentQMV2[0].y) {
311                            CHECK_CANDIDATE(xo-1, (yo+yo2)>>1, 0);
312                            CHECK_CANDIDATE(xo+1, (yo+yo2)>>1, 0);
313                            goto ende;
314                    }
315                    else {
316                            CHECK_CANDIDATE((data->currentQMV[0].y == yo) ? data->currentQMV[0].x : data->currentQMV2[0].x, (yo+yo2)>>1, 0);
317                            goto ende;
318                    }
319            }
320    
321            CHECK_CANDIDATE(xo, (yo+yo2)>>1, 0);
322            CHECK_CANDIDATE((xo+xo2)>>1, yo, 0);
323    
324            if(best_sad <= *data->iMinSAD2)
325                    goto ende;
326    
327            CHECK_CANDIDATE((xo+xo2)>>1, (yo+yo2)>>1, 0);
328    
329    ende:
330            CheckCandidate = backupFunc;
331    }
332    
333    int
334    xvid_me_SkipDecisionP(const IMAGE * current, const IMAGE * reference,
335                                                            const int x, const int y,
336                                                            const uint32_t stride, const uint32_t iQuant, int rrv)
337    {
338            int offset = (x + y*stride)*8;
339            if(!rrv) {
340                    uint32_t sadC = sad8(current->u + offset,
341                                                    reference->u + offset, stride);
342                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
343                    sadC += sad8(current->v + offset,
344                                                    reference->v + offset, stride);
345                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP) return 0;
346                    return 1;
347    
348            } else {
349                    uint32_t sadC = sad16(current->u + 2*offset,
350                                                    reference->u + 2*offset, stride, 256*4096);
351                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
352                    sadC += sad16(current->v + 2*offset,
353                                                    reference->v + 2*offset, stride, 256*4096);
354                    if (sadC > iQuant * MAX_CHROMA_SAD_FOR_SKIP*4) return 0;
355                    return 1;
356            }
357    }
358    
359            /*
360             * pmv are filled with:
361             *  [0]: Median (or whatever is correct in a special case)
362             *  [1]: left neighbour
363             *  [2]: top neighbour
364             *  [3]: topright neighbour
365             * psad are filled with:
366             *  [0]: minimum of [1] to [3]
367             *  [1]: left neighbour's SAD (NB:[1] to [3] are actually not needed)
368             *  [2]: top neighbour's SAD
369             *  [3]: topright neighbour's SAD
370             */
371    
372    static __inline int
373    get_pmvdata2(const MACROBLOCK * const mbs,
374                    const int mb_width,
375                    const int bound,
376                    const int x,
377                    const int y,
378                    const int block,
379                    VECTOR * const pmv,
380                    int32_t * const psad)
381    {
382            int lx, ly, lz;         /* left */
383            int tx, ty, tz;         /* top */
384            int rx, ry, rz;         /* top-right */
385            int lpos, tpos, rpos;
386            int num_cand = 0, last_cand = 1;
387    
388            switch (block) {
389            case 0:
390                    lx = x - 1;     ly = y;         lz = 1;
391                    tx = x;         ty = y - 1;     tz = 2;
392                    rx = x + 1;     ry = y - 1;     rz = 2;
393                    break;
394            case 1:
395                    lx = x;         ly = y;         lz = 0;
396                    tx = x;         ty = y - 1;     tz = 3;
397                    rx = x + 1;     ry = y - 1;     rz = 2;
398                    break;
399            case 2:
400                    lx = x - 1;     ly = y;         lz = 3;
401                    tx = x;         ty = y;         tz = 0;
402                    rx = x;         ry = y;         rz = 1;
403                    break;
404            default:
405                    lx = x;         ly = y;         lz = 2;
406                    tx = x;         ty = y;         tz = 0;
407                    rx = x;         ry = y;         rz = 1;
408            }
409    
410            lpos = lx + ly * mb_width;
411            rpos = rx + ry * mb_width;
412            tpos = tx + ty * mb_width;
413    
414            if (lpos >= bound && lx >= 0) {
415                    num_cand++;
416                    last_cand = 1;
417                    pmv[1] = mbs[lpos].mvs[lz];
418                    psad[1] = mbs[lpos].sad8[lz];
419            } else {
420                    pmv[1] = zeroMV;
421                    psad[1] = MV_MAX_ERROR;
422            }
423    
424            if (tpos >= bound) {
425                    num_cand++;
426                    last_cand = 2;
427                    pmv[2]= mbs[tpos].mvs[tz];
428                    psad[2] = mbs[tpos].sad8[tz];
429            } else {
430                    pmv[2] = zeroMV;
431                    psad[2] = MV_MAX_ERROR;
432            }
433    
434            if (rpos >= bound && rx < mb_width) {
435                    num_cand++;
436                    last_cand = 3;
437                    pmv[3] = mbs[rpos].mvs[rz];
438                    psad[3] = mbs[rpos].sad8[rz];
439            } else {
440                    pmv[3] = zeroMV;
441                    psad[3] = MV_MAX_ERROR;
442            }
443    
444            /* original pmvdata() compatibility hack */
445            if (x == 0 && y == 0 && block == 0) {
446                    pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
447                    psad[0] = 0;
448                    psad[1] = psad[2] = psad[3] = MV_MAX_ERROR;
449                    return 0;
450            }
451    
452            /* if only one valid candidate preictor, the invalid candiates are set to the canidate */
453            if (num_cand == 1) {
454                    pmv[0] = pmv[last_cand];
455                    psad[0] = psad[last_cand];
456    #if 0
457                    return MVequal(pmv[0], zeroMV); /* no point calculating median mv and minimum sad */
458    #endif
459    
460                    /* original pmvdata() compatibility hack */
461                    return y==0 && block <= 1 ? 0 : MVequal(pmv[0], zeroMV);
462            }
463    
464            if ((MVequal(pmv[1], pmv[2])) && (MVequal(pmv[1], pmv[3]))) {
465                    pmv[0] = pmv[1];
466                    psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]);
467                    return 1;
468            }
469    
470            /* set median, minimum */
471    
472            pmv[0].x =
473                    MIN(MAX(pmv[1].x, pmv[2].x),
474                            MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
475            pmv[0].y =
476                    MIN(MAX(pmv[1].y, pmv[2].y),
477                            MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
478    
479            psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]);
480    
481            return 0;
482    }
483    
484    
485    static void
486    ModeDecision_SAD(SearchData * const Data,
487                                    MACROBLOCK * const pMB,
488                                    const MACROBLOCK * const pMBs,
489                                    const int x, const int y,
490                                    const MBParam * const pParam,
491                                    const uint32_t MotionFlags,
492                                    const uint32_t VopFlags,
493                                    const uint32_t VolFlags,
494                                    const IMAGE * const pCurrent,
495                                    const IMAGE * const pRef,
496                                    const IMAGE * const vGMC,
497                                    const int coding_type)
498    {
499            int mode = MODE_INTER;
500            int mcsel = 0;
501            int inter4v = (VopFlags & XVID_VOP_INTER4V) && (pMB->dquant == 0);
502            const uint32_t iQuant = pMB->quant;
503    
504            const int skip_possible = (coding_type == P_VOP) && (pMB->dquant == 0);
505    
506            int sad;
507            int InterBias = MV16_INTER_BIAS;
508    
509            pMB->mcsel = 0;
510    
511            if (inter4v == 0 || Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] +
512                    Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant) {
513                    mode = MODE_INTER;
514                    sad = Data->iMinSAD[0];
515            } else {
516                    mode = MODE_INTER4V;
517                    sad = Data->iMinSAD[1] + Data->iMinSAD[2] +
518                                            Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * (int32_t)iQuant;
519                    Data->iMinSAD[0] = sad;
520            }
521    
522            /* final skip decision, a.k.a. "the vector you found, really that good?" */
523            if (skip_possible && (pMB->sad16 < (int)iQuant * MAX_SAD00_FOR_SKIP))
524                    if ( (100*sad)/(pMB->sad16+1) > FINAL_SKIP_THRESH)
525                            if (Data->chroma || xvid_me_SkipDecisionP(pCurrent, pRef, x, y, Data->iEdgedWidth/2, iQuant, Data->rrv)) {
526                                    mode = MODE_NOT_CODED;
527                                    sad = 0;
528                            }
529    
530            /* mcsel */
531            if (coding_type == S_VOP) {
532    
533                    int32_t iSAD = sad16(Data->Cur,
534                            vGMC->y + 16*y*Data->iEdgedWidth + 16*x, Data->iEdgedWidth, 65536);
535    
536                    if (Data->chroma) {
537                            iSAD += sad8(Data->CurU, vGMC->u + 8*y*(Data->iEdgedWidth/2) + 8*x, Data->iEdgedWidth/2);
538                            iSAD += sad8(Data->CurV, vGMC->v + 8*y*(Data->iEdgedWidth/2) + 8*x, Data->iEdgedWidth/2);
539                    }
540    
541                    if (iSAD <= sad) {              /* mode decision GMC */
542                            mode = MODE_INTER;
543                            mcsel = 1;
544                            sad = iSAD;
545                    }
546            }
547    
548            /* intra decision */
549    
550            if (iQuant > 8) InterBias += 100 * (iQuant - 8); /* to make high quants work */
551            if (y != 0)
552                    if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80;
553            if (x != 0)
554                    if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80;
555    
556            if (Data->chroma) InterBias += 50; /* dev8(chroma) ??? <-- yes, we need dev8 (no big difference though) */
557            if (Data->rrv) InterBias *= 4;
558    
559            if (InterBias < sad) {
560                    int32_t deviation;
561                    if (!Data->rrv)
562                            deviation = dev16(Data->Cur, Data->iEdgedWidth);
563                    else
564                            deviation = dev16(Data->Cur, Data->iEdgedWidth) + /* dev32() */
565                                                    dev16(Data->Cur+16, Data->iEdgedWidth) +
566                                                    dev16(Data->Cur + 16*Data->iEdgedWidth, Data->iEdgedWidth) +
567                                                    dev16(Data->Cur+16+16*Data->iEdgedWidth, Data->iEdgedWidth);
568    
569                    if (deviation < (sad - InterBias)) mode = MODE_INTRA;
570            }
571    
572            pMB->cbp = 63;
573            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;
574    
575            if (Data->rrv) {
576                            Data->currentMV[0].x = RRV_MV_SCALEDOWN(Data->currentMV[0].x);
577                            Data->currentMV[0].y = RRV_MV_SCALEDOWN(Data->currentMV[0].y);
578            }
579    
580            if (mode == MODE_INTER && mcsel == 0) {
581                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
582    
583                    if(Data->qpel) {
584                            pMB->qmvs[0] = pMB->qmvs[1]
585                                    = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
586                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predMV.x;
587                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predMV.y;
588                    } else {
589                            pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
590                            pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
591                    }
592    
593            } else if (mode == MODE_INTER ) { /* but mcsel == 1 */
594    
595                    pMB->mcsel = 1;
596                    if (Data->qpel) {
597                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = pMB->amv;
598                            pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = pMB->amv.x/2;
599                            pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = pMB->amv.y/2;
600                    } else
601                            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv;
602    
603            } else
604                    if (mode == MODE_INTER4V) ; /* anything here? */
605            else    /* INTRA, NOT_CODED */
606                    ZeroMacroblockP(pMB, 0);
607    
608            pMB->mode = mode;
609    }
610    
611    static __inline void
612    PreparePredictionsP(VECTOR * const pmv, int x, int y, int iWcount,
613                            int iHcount, const MACROBLOCK * const prevMB, int rrv)
614    {
615            /* this function depends on get_pmvdata which means that it sucks. It should get the predictions by itself */
616            if (rrv) { iWcount /= 2; iHcount /= 2; }
617    
618            if ( (y != 0) && (x < (iWcount-1)) ) {          /* [5] top-right neighbour */
619                    pmv[5].x = EVEN(pmv[3].x);
620                    pmv[5].y = EVEN(pmv[3].y);
621            } else pmv[5].x = pmv[5].y = 0;
622    
623            if (x != 0) { pmv[3].x = EVEN(pmv[1].x); pmv[3].y = EVEN(pmv[1].y); }/* pmv[3] is left neighbour */
624            else pmv[3].x = pmv[3].y = 0;
625    
626            if (y != 0) { pmv[4].x = EVEN(pmv[2].x); pmv[4].y = EVEN(pmv[2].y); }/* [4] top neighbour */
627            else pmv[4].x = pmv[4].y = 0;
628    
629            /* [1] median prediction */
630            pmv[1].x = EVEN(pmv[0].x); pmv[1].y = EVEN(pmv[0].y);
631    
632            pmv[0].x = pmv[0].y = 0; /* [0] is zero; not used in the loop (checked before) but needed here for make_mask */
633    
634            pmv[2].x = EVEN(prevMB->mvs[0].x); /* [2] is last frame */
635            pmv[2].y = EVEN(prevMB->mvs[0].y);
636    
637            if ((x < iWcount-1) && (y < iHcount-1)) {
638                    pmv[6].x = EVEN((prevMB+1+iWcount)->mvs[0].x); /* [6] right-down neighbour in last frame */
639                    pmv[6].y = EVEN((prevMB+1+iWcount)->mvs[0].y);
640            } else pmv[6].x = pmv[6].y = 0;
641    
642            if (rrv) {
643                    int i;
644                    for (i = 0; i < 7; i++) {
645                            pmv[i].x = RRV_MV_SCALEUP(pmv[i].x);
646                            pmv[i].y = RRV_MV_SCALEUP(pmv[i].y);
647                    }
648            }
649    }
650    
651    static void
652    Search8(const SearchData * const OldData,
653                    const int x, const int y,
654                    const uint32_t MotionFlags,
655                    const MBParam * const pParam,
656                    MACROBLOCK * const pMB,
657                    const MACROBLOCK * const pMBs,
658                    const int block,
659                    SearchData * const Data)
660    {
661            int i = 0;
662            CheckFunc * CheckCandidate;
663            Data->iMinSAD = OldData->iMinSAD + 1 + block;
664            Data->currentMV = OldData->currentMV + 1 + block;
665            Data->currentQMV = OldData->currentQMV + 1 + block;
666    
667            if(Data->qpel) {
668                    Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
669                    if (block != 0) i = d_mv_bits(  Data->currentQMV->x, Data->currentQMV->y,
670                                                                                    Data->predMV, Data->iFcode, 0, 0);
671            } else {
672                    Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2, y/2, block);
673                    if (block != 0) i = d_mv_bits(  Data->currentMV->x, Data->currentMV->y,
674                                                                                    Data->predMV, Data->iFcode, 0, Data->rrv);
675            }
676    
677            *(Data->iMinSAD) += (Data->lambda8 * i * (*Data->iMinSAD + NEIGH_8X8_BIAS))>>10;
678    
679            if (MotionFlags & (XVID_ME_EXTSEARCH8|XVID_ME_HALFPELREFINE8|XVID_ME_QUARTERPELREFINE8)) {
680    
681                    if (Data->rrv) i = 16; else i = 8;
682    
683                    Data->RefP[0] = OldData->RefP[0] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
684                    Data->RefP[1] = OldData->RefP[1] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
685                    Data->RefP[2] = OldData->RefP[2] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
686                    Data->RefP[3] = OldData->RefP[3] + i * ((block&1) + Data->iEdgedWidth*(block>>1));
687    
688                    Data->Cur = OldData->Cur + i * ((block&1) + Data->iEdgedWidth*(block>>1));
689                    Data->qpel_precision = 0;
690    
691                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 3,
692                                            pParam->width, pParam->height, Data->iFcode - Data->qpel, 1, Data->rrv);
693    
694                    if (!Data->rrv) CheckCandidate = CheckCandidate8;
695                    else CheckCandidate = CheckCandidate16no4v;
696    
697                    if (MotionFlags & XVID_ME_EXTSEARCH8 && (!(MotionFlags & XVID_ME_EXTSEARCH_RD))) {
698                            int32_t temp_sad = *(Data->iMinSAD); /* store current MinSAD */
699    
700                            MainSearchFunc *MainSearchPtr;
701                            if (MotionFlags & XVID_ME_USESQUARES8) MainSearchPtr = xvid_me_SquareSearch;
702                                    else if (MotionFlags & XVID_ME_ADVANCEDDIAMOND8) MainSearchPtr = xvid_me_AdvDiamondSearch;
703                                            else MainSearchPtr = xvid_me_DiamondSearch;
704    
705                            MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, 255, CheckCandidate);
706    
707                            if(*(Data->iMinSAD) < temp_sad) {
708                                            Data->currentQMV->x = 2 * Data->currentMV->x; /* update our qpel vector */
709                                            Data->currentQMV->y = 2 * Data->currentMV->y;
710                            }
711                    }
712    
713                    if (MotionFlags & XVID_ME_HALFPELREFINE8) {
714                            int32_t temp_sad = *(Data->iMinSAD); /* store current MinSAD */
715    
716                            xvid_me_SubpelRefine(Data, CheckCandidate); /* perform halfpel refine of current best vector */
717    
718                            if(*(Data->iMinSAD) < temp_sad) { /* we have found a better match */
719                                    Data->currentQMV->x = 2 * Data->currentMV->x; /* update our qpel vector */
720                                    Data->currentQMV->y = 2 * Data->currentMV->y;
721                            }
722                    }
723    
724                    if (Data->qpel && MotionFlags & XVID_ME_QUARTERPELREFINE8) {
725                                    Data->qpel_precision = 1;
726                                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 3,
727                                            pParam->width, pParam->height, Data->iFcode, 2, 0);
728                                    xvid_me_SubpelRefine(Data, CheckCandidate);
729                    }
730            }
731    
732            if (Data->rrv) {
733                            Data->currentMV->x = RRV_MV_SCALEDOWN(Data->currentMV->x);
734                            Data->currentMV->y = RRV_MV_SCALEDOWN(Data->currentMV->y);
735            }
736    
737            if(Data->qpel) {
738                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predMV.x;
739                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predMV.y;
740                    pMB->qmvs[block] = *Data->currentQMV;
741            } else {
742                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
743                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
744            }
745    
746            pMB->mvs[block] = *Data->currentMV;
747            pMB->sad8[block] = 4 * *Data->iMinSAD;
748    }
749    
750    
751    
752    static void
753    SearchP(const IMAGE * const pRef,
754                    const uint8_t * const pRefH,
755                    const uint8_t * const pRefV,
756                    const uint8_t * const pRefHV,
757                    const IMAGE * const pCur,
758                    const int x,
759                    const int y,
760                    const uint32_t MotionFlags,
761                    const uint32_t VopFlags,
762                    SearchData * const Data,
763                    const MBParam * const pParam,
764                    const MACROBLOCK * const pMBs,
765                    const MACROBLOCK * const prevMBs,
766                    MACROBLOCK * const pMB)
767    {
768    
769            int i, threshA;
770            VECTOR pmv[7];
771            int inter4v = (VopFlags & XVID_VOP_INTER4V) && (pMB->dquant == 0);
772            CheckFunc * CheckCandidate;
773    
774            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
775                                                    pParam->width, pParam->height, Data->iFcode - Data->qpel, 1, Data->rrv);
776    
777            get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);
778    
779            Data->temp[5] = Data->temp[6] = 0; /* chroma-sad cache */
780            i = Data->rrv ? 2 : 1;
781            Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16*i;
782            Data->CurV = pCur->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
783            Data->CurU = pCur->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
784    
785            Data->RefP[0] = pRef->y + (x + Data->iEdgedWidth*y) * 16*i;
786            Data->RefP[2] = pRefH + (x + Data->iEdgedWidth*y) * 16*i;
787            Data->RefP[1] = pRefV + (x + Data->iEdgedWidth*y) * 16*i;
788            Data->RefP[3] = pRefHV + (x + Data->iEdgedWidth*y) * 16*i;
789            Data->RefP[4] = pRef->u + (x + y * (Data->iEdgedWidth/2)) * 8*i;
790            Data->RefP[5] = pRef->v + (x + y * (Data->iEdgedWidth/2)) * 8*i;
791    
792            Data->lambda16 = xvid_me_lambda_vec16[pMB->quant];
793            Data->lambda8 = xvid_me_lambda_vec8[pMB->quant];
794            Data->qpel_precision = 0;
795            *Data->dir = 0;
796    
797            memset(Data->currentMV, 0, 5*sizeof(VECTOR));
798    
799            if (Data->qpel) Data->predMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
800            else Data->predMV = pmv[0];
801    
802            i = d_mv_bits(0, 0, Data->predMV, Data->iFcode, 0, 0);
803            Data->iMinSAD[0] = pMB->sad16 + ((Data->lambda16 * i * pMB->sad16)>>10);
804            Data->iMinSAD[1] = pMB->sad8[0] + ((Data->lambda8 * i * (pMB->sad8[0]+NEIGH_8X8_BIAS)) >> 10);
805            Data->iMinSAD[2] = pMB->sad8[1];
806            Data->iMinSAD[3] = pMB->sad8[2];
807            Data->iMinSAD[4] = pMB->sad8[3];
808    
809            if ((!(VopFlags & XVID_VOP_MODEDECISION_RD)) && (x | y)) {
810                    threshA = Data->temp[0]; /* that's where we keep this SAD atm */
811                    if (threshA < 512) threshA = 512;
812                    else if (threshA > 1024) threshA = 1024;
813            } else
814                    threshA = 512;
815    
816            PreparePredictionsP(pmv, x, y, pParam->mb_width, pParam->mb_height,
817                                            prevMBs + x + y * pParam->mb_width, Data->rrv);
818    
819            if (!Data->rrv) {
820                    if (inter4v) CheckCandidate = CheckCandidate16;
821                            else CheckCandidate = CheckCandidate16no4v; /* for extra speed */
822            } else CheckCandidate = CheckCandidate32;
823    
824    /* main loop. checking all predictions (but first, which is 0,0 and has been checked in MotionEstimation())*/
825    
826            for (i = 1; i < 7; i++)
827                    if (!vector_repeats(pmv, i)) {
828                            CheckCandidate(pmv[i].x, pmv[i].y, Data, i);
829                            if (Data->iMinSAD[0] <= threshA) { i++; break; }
830                    }
831    
832            if ((Data->iMinSAD[0] <= threshA) ||
833                            (MVequal(Data->currentMV[0], (prevMBs+x+y*pParam->mb_width)->mvs[0]) &&
834                            (Data->iMinSAD[0] < (prevMBs+x+y*pParam->mb_width)->sad16)))
835                    inter4v = 0;
836            else {
837    
838                    MainSearchFunc * MainSearchPtr;
839                    int mask = make_mask(pmv, i, *Data->dir); /* all vectors pmv[0..i-1] have been checked */
840    
841                    if (MotionFlags & XVID_ME_USESQUARES16) MainSearchPtr = xvid_me_SquareSearch;
842                    else if (MotionFlags & XVID_ME_ADVANCEDDIAMOND16) MainSearchPtr = xvid_me_AdvDiamondSearch;
843                            else MainSearchPtr = xvid_me_DiamondSearch;
844    
845                    MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, mask, CheckCandidate);
846    
847    /* extended search, diamond starting in 0,0 and in prediction.
848            note that this search is/might be done in halfpel positions,
849            which makes it more different than the diamond above */
850    
851                    if (MotionFlags & XVID_ME_EXTSEARCH16) {
852                            int32_t bSAD;
853                            VECTOR startMV = Data->predMV, backupMV = Data->currentMV[0];
854                            if (Data->rrv) {
855                                    startMV.x = RRV_MV_SCALEUP(startMV.x);
856                                    startMV.y = RRV_MV_SCALEUP(startMV.y);
857                            }
858                            if (!(MVequal(startMV, backupMV))) {
859                                    bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
860    
861                                    CheckCandidate(startMV.x, startMV.y, Data, 255);
862                                    MainSearchPtr(startMV.x, startMV.y, Data, 255, CheckCandidate);
863                                    if (bSAD < Data->iMinSAD[0]) {
864                                            Data->currentMV[0] = backupMV;
865                                            Data->iMinSAD[0] = bSAD; }
866                            }
867    
868                            backupMV = Data->currentMV[0];
869                            startMV.x = startMV.y = 1;
870                            if (!(MVequal(startMV, backupMV))) {
871                                    bSAD = Data->iMinSAD[0]; Data->iMinSAD[0] = MV_MAX_ERROR;
872    
873                                    CheckCandidate(startMV.x, startMV.y, Data, 255);
874                                    MainSearchPtr(startMV.x, startMV.y, Data, 255, CheckCandidate);
875                                    if (bSAD < Data->iMinSAD[0]) {
876                                            Data->currentMV[0] = backupMV;
877                                            Data->iMinSAD[0] = bSAD;
878                                    }
879                            }
880                    }
881            }
882    
883            if (MotionFlags & XVID_ME_HALFPELREFINE16)
884                            xvid_me_SubpelRefine(Data, CheckCandidate);
885    
886            for(i = 0; i < 5; i++) {
887                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; /* initialize qpel vectors */
888                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
889            }
890    
891            if (Data->qpel) {
892                    get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
893                                    pParam->width, pParam->height, Data->iFcode, 2, 0);
894                    Data->qpel_precision = 1;
895                    if (MotionFlags & XVID_ME_QUARTERPELREFINE16) {
896                            if(MotionFlags & XVID_ME_FASTREFINE16)
897                                    SubpelRefine_Fast(Data, CheckCandidate);
898                            else
899                                    xvid_me_SubpelRefine(Data, CheckCandidate);
900                    }
901            }
902    
903            if (Data->iMinSAD[0] < (int32_t)pMB->quant * 30)
904                    inter4v = 0;
905    
906            if (inter4v) {
907                    SearchData Data8;
908                    memcpy(&Data8, Data, sizeof(SearchData)); /* quick copy of common data */
909    
910                    Search8(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
911                    Search8(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
912                    Search8(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
913                    Search8(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
914    
915                    if ((Data->chroma) && (!(VopFlags & XVID_VOP_MODEDECISION_RD))) {
916                            /* chroma is only used for comparsion to INTER. if the comparsion will be done in BITS domain, it will not be used */
917                            int sumx = 0, sumy = 0;
918    
919                            if (Data->qpel)
920                                    for (i = 1; i < 5; i++) {
921                                            sumx += Data->currentQMV[i].x/2;
922                                            sumy += Data->currentQMV[i].y/2;
923                                    }
924                            else
925                                    for (i = 1; i < 5; i++) {
926                                            sumx += Data->currentMV[i].x;
927                                            sumy += Data->currentMV[i].y;
928                                    }
929    
930                            Data->iMinSAD[1] += xvid_me_ChromaSAD((sumx >> 3) + roundtab_76[sumx & 0xf],
931                                                                                                    (sumy >> 3) + roundtab_76[sumy & 0xf], Data);
932                    }
933            } else Data->iMinSAD[1] = 4096*256;
934    }
935    
936    static __inline uint32_t
937    MakeGoodMotionFlags(const uint32_t MotionFlags, const uint32_t VopFlags, const uint32_t VolFlags)
938    {
939            uint32_t Flags = MotionFlags;
940    
941            if (!(VopFlags & XVID_VOP_MODEDECISION_RD))
942                    Flags &= ~(XVID_ME_QUARTERPELREFINE16_RD+XVID_ME_QUARTERPELREFINE8_RD+XVID_ME_HALFPELREFINE16_RD+XVID_ME_HALFPELREFINE8_RD+XVID_ME_EXTSEARCH_RD);
943    
944            if (Flags & XVID_ME_EXTSEARCH_RD)
945                    Flags |= XVID_ME_HALFPELREFINE16_RD;
946    
947            if (Flags & XVID_ME_EXTSEARCH_RD && MotionFlags & XVID_ME_EXTSEARCH8)
948                    Flags |= XVID_ME_HALFPELREFINE8_RD;
949    
950            if (Flags & XVID_ME_HALFPELREFINE16_RD)
951                    Flags |= XVID_ME_QUARTERPELREFINE16_RD;
952    
953            if (Flags & XVID_ME_HALFPELREFINE8_RD) {
954                    Flags |= XVID_ME_QUARTERPELREFINE8_RD;
955                    Flags &= ~XVID_ME_HALFPELREFINE8;
956            }
957    
958            if (Flags & XVID_ME_QUARTERPELREFINE8_RD)
959                    Flags &= ~XVID_ME_QUARTERPELREFINE8;
960    
961            if (!(VolFlags & XVID_VOL_QUARTERPEL))
962                    Flags &= ~(XVID_ME_QUARTERPELREFINE16+XVID_ME_QUARTERPELREFINE8+XVID_ME_QUARTERPELREFINE16_RD+XVID_ME_QUARTERPELREFINE8_RD);
963    
964            if (!(VopFlags & XVID_VOP_HALFPEL))
965                    Flags &= ~(XVID_ME_EXTSEARCH16+XVID_ME_HALFPELREFINE16+XVID_ME_HALFPELREFINE8+XVID_ME_HALFPELREFINE16_RD+XVID_ME_HALFPELREFINE8_RD);
966    
967            if ((VopFlags & XVID_VOP_GREYSCALE) || (VopFlags & XVID_VOP_REDUCED))
968                    Flags &= ~(XVID_ME_CHROMA_PVOP + XVID_ME_CHROMA_BVOP);
969    
970            return Flags;
971    }
972    
973    bool
974    MotionEstimation(MBParam * const pParam,
975                                     FRAMEINFO * const current,
976                                     FRAMEINFO * const reference,
977                                     const IMAGE * const pRefH,
978                                     const IMAGE * const pRefV,
979                                     const IMAGE * const pRefHV,
980                                    const IMAGE * const pGMC,
981                                     const uint32_t iLimit)
982    {
983            MACROBLOCK *const pMBs = current->mbs;
984            const IMAGE *const pCurrent = &current->image;
985            const IMAGE *const pRef = &reference->image;
986    
987            uint32_t mb_width = pParam->mb_width;
988            uint32_t mb_height = pParam->mb_height;
989            const uint32_t iEdgedWidth = pParam->edged_width;
990            const uint32_t MotionFlags = MakeGoodMotionFlags(current->motion_flags, current->vop_flags, current->vol_flags);
991            int stat_thresh = 0;
992    
993            uint32_t x, y;
994            uint32_t iIntra = 0;
995            int32_t sad00;
996            int skip_thresh = INITIAL_SKIP_THRESH * \
997                    (current->vop_flags & XVID_VOP_REDUCED ? 4:1) * \
998                    (current->vop_flags & XVID_VOP_MODEDECISION_RD ? 2:1);
999    
1000            /* some pre-initialized thingies for SearchP */
1001            int32_t temp[8]; uint32_t dir;
1002            VECTOR currentMV[5];
1003            VECTOR currentQMV[5];
1004            VECTOR currentMV2[5];
1005            VECTOR currentQMV2[5];
1006            int32_t iMinSAD[5];
1007            int32_t iMinSAD2[5];
1008            DECLARE_ALIGNED_MATRIX(dct_space, 3, 64, int16_t, CACHE_LINE);
1009            SearchData Data;
1010            memset(&Data, 0, sizeof(SearchData));
1011            Data.iEdgedWidth = iEdgedWidth;
1012            Data.currentMV = currentMV;
1013            Data.currentQMV = currentQMV;
1014            Data.currentMV2 = currentMV2;
1015            Data.currentQMV2 = currentQMV2;
1016            Data.iMinSAD = iMinSAD;
1017            Data.iMinSAD2 = iMinSAD2;
1018            Data.temp = temp;
1019            Data.dir = &dir;
1020            Data.iFcode = current->fcode;
1021            Data.rounding = pParam->m_rounding_type;
1022            Data.qpel = (current->vol_flags & XVID_VOL_QUARTERPEL ? 1:0);
1023            Data.chroma = MotionFlags & XVID_ME_CHROMA_PVOP;
1024            Data.rrv = (current->vop_flags & XVID_VOP_REDUCED) ? 1:0;
1025            Data.dctSpace = dct_space;
1026            Data.quant_type = !(pParam->vol_flags & XVID_VOL_MPEGQUANT);
1027    
1028            if ((current->vop_flags & XVID_VOP_REDUCED)) {
1029                    mb_width = (pParam->width + 31) / 32;
1030                    mb_height = (pParam->height + 31) / 32;
1031                    Data.qpel = 0;
1032            }
1033    
1034            Data.RefQ = pRefV->u; /* a good place, also used in MC (for similar purpose) */
1035            if (sadInit) (*sadInit) ();
1036    
1037            for (y = 0; y < mb_height; y++) {
1038                    for (x = 0; x < mb_width; x++)  {
1039                            MACROBLOCK *pMB = &pMBs[x + y * pParam->mb_width];
1040                            MACROBLOCK *prevMB = &reference->mbs[x + y * pParam->mb_width];
1041    
1042                            if (!Data.rrv) pMB->sad16 =
1043                                    sad16v(pCurrent->y + (x + y * iEdgedWidth) * 16,
1044                                                            pRef->y + (x + y * iEdgedWidth) * 16,
1045                                                            pParam->edged_width, pMB->sad8 );
1046    
1047                            else pMB->sad16 =
1048                                    sad32v_c(pCurrent->y + (x + y * iEdgedWidth) * 32,
1049                                                            pRef->y + (x + y * iEdgedWidth) * 32,
1050                                                            pParam->edged_width, pMB->sad8 );
1051    
1052                            if (Data.chroma) {
1053                                    Data.temp[7] = sad8(pCurrent->u + x*8 + y*(iEdgedWidth/2)*8,
1054                                                                            pRef->u + x*8 + y*(iEdgedWidth/2)*8, iEdgedWidth/2)
1055                                                                    + sad8(pCurrent->v + (x + y*(iEdgedWidth/2))*8,
1056                                                                            pRef->v + (x + y*(iEdgedWidth/2))*8, iEdgedWidth/2);
1057                                    pMB->sad16 += Data.temp[7];
1058                            }
1059    
1060                            sad00 = pMB->sad16;
1061    
1062                            /* initial skip decision */
1063                            /* no early skip for GMC (global vector = skip vector is unknown!)  */
1064                            if (current->coding_type != S_VOP)      { /* no fast SKIP for S(GMC)-VOPs */
1065                                    if (pMB->dquant == 0 && sad00 < pMB->quant * skip_thresh)
1066                                            if (Data.chroma || xvid_me_SkipDecisionP(pCurrent, pRef, x, y, iEdgedWidth/2, pMB->quant, Data.rrv)) {
1067                                                    ZeroMacroblockP(pMB, sad00);
1068                                                    pMB->mode = MODE_NOT_CODED;
1069                                                    continue;
1070                                            }
1071                            }
1072    
1073                            if(MotionFlags & XVID_ME_DETECT_STATIC_MOTION) {
1074                                    if(x > 0 && y > 0 && x < pParam->mb_width) {
1075                                            if(MVequal((&pMBs[(x-1) + y * pParam->mb_width])->mvs[0], zeroMV) &&
1076                                               MVequal((&pMBs[x + (y-1) * pParam->mb_width])->mvs[0], zeroMV) &&
1077                                           MVequal((&pMBs[(x+1) + (y-1) * pParam->mb_width])->mvs[0], zeroMV) &&
1078                                           MVequal(prevMB->mvs[0], zeroMV)) {
1079                                                    stat_thresh = MAX((&pMBs[(x-1) + y * pParam->mb_width])->sad16,
1080                                                                              MAX((&pMBs[x + (y-1) * pParam->mb_width])->sad16,
1081                                                                              MAX((&pMBs[(x+1) + (y-1) * pParam->mb_width])->sad16,
1082                                                                              prevMB->sad16)));
1083                                            }
1084                                    } else {
1085                                            stat_thresh = MIN((&pMBs[(x-1) + y * pParam->mb_width])->sad16,
1086                                                                              MIN((&pMBs[x + (y-1) * pParam->mb_width])->sad16,
1087                                                                              MIN((&pMBs[(x+1) + (y-1) * pParam->mb_width])->sad16,
1088                                                                              prevMB->sad16)));
1089                                    }
1090                            }
1091    
1092                             /* favorize (0,0) vector for cartoons */
1093                            if ((current->vop_flags & XVID_VOP_CARTOON) &&
1094                                    ((sad00 < pMB->quant * 4 * skip_thresh) || (sad00 < stat_thresh))) {
1095                                    ZeroMacroblockP(pMB, sad00);
1096                                    continue;
1097                            }
1098    
1099                            SearchP(pRef, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
1100                                            y, MotionFlags, current->vop_flags,
1101                                            &Data, pParam, pMBs, reference->mbs, pMB);
1102    
1103                            if (current->vop_flags & XVID_VOP_MODEDECISION_RD)
1104                                    xvid_me_ModeDecision_RD(&Data, pMB, pMBs, x, y, pParam,
1105                                                                    MotionFlags, current->vop_flags, current->vol_flags,
1106                                                                    pCurrent, pRef, pGMC, current->coding_type);
1107    
1108                            else if (current->vop_flags & XVID_VOP_FAST_MODEDECISION_RD)
1109                                    xvid_me_ModeDecision_Fast(&Data, pMB, pMBs, x, y, pParam,
1110                                                                    MotionFlags, current->vop_flags, current->vol_flags,
1111                                                                    pCurrent, pRef, pGMC, current->coding_type);
1112                            else
1113                                    ModeDecision_SAD(&Data, pMB, pMBs, x, y, pParam,
1114                                                                    MotionFlags, current->vop_flags, current->vol_flags,
1115                                                                    pCurrent, pRef, pGMC, current->coding_type);
1116    
1117    
1118                            if (pMB->mode == MODE_INTRA)
1119                                    if (++iIntra > iLimit) return 1;
1120                    }
1121            }
1122            return 0;
1123    }
1124    
1125    

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