[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.1.2.1, Wed Sep 10 22:18:59 2003 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, const 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->temp[5] && dy == data->temp[6]) return data->temp[7]; /* it has been checked recently */
89            data->temp[5] = dx; data->temp[6] = dy; /* backup */
90    
91            switch (((dx & 1) << 1) | (dy & 1))     {
92                    case 0:
93                            sad = sad8(data->CurU, data->RefP[4] + offset, stride);
94                            sad += sad8(data->CurV, data->RefP[5] + offset, stride);
95                            break;
96                    case 1:
97                            next = stride;
98                    case 2:
99                            sad = sad8bi(data->CurU, data->RefP[4] + offset, data->RefP[4] + offset + next, stride);
100                            sad += sad8bi(data->CurV, data->RefP[5] + offset, data->RefP[5] + offset + next, stride);
101                            break;
102                    default:
103                            interpolate8x8_halfpel_hv(data->RefQ, data->RefP[4] + offset, stride, data->rounding);
104                            sad = sad8(data->CurU, data->RefQ, stride);
105    
106                            interpolate8x8_halfpel_hv(data->RefQ, data->RefP[5] + offset, stride, data->rounding);
107                            sad += sad8(data->CurV, data->RefQ, stride);
108                            break;
109            }
110            data->temp[7] = sad; /* backup, part 2 */
111            return sad;
112    }
113    
114    uint8_t *
115    xvid_me_interpolate8x8qpel(const int x, const int y, const uint32_t block, const uint32_t dir, const SearchData * const data)
116    {
117            /* create or find a qpel-precision reference picture; return pointer to it */
118            uint8_t * Reference = data->RefQ + 16*dir;
119            const uint32_t iEdgedWidth = data->iEdgedWidth;
120            const uint32_t rounding = data->rounding;
121            const int halfpel_x = x/2;
122            const int halfpel_y = y/2;
123            const uint8_t *ref1, *ref2, *ref3, *ref4;
124    
125            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
126            ref1 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
127            switch( ((x&1)<<1) + (y&1) ) {
128            case 3: /* x and y in qpel resolution - the "corners" (top left/right and */
129                            /* bottom left/right) during qpel refinement */
130                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
131                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
132                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
133                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
134                    ref3 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
135                    ref4 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
136                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
137                    break;
138    
139            case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
140                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
141                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
142                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
143                    break;
144    
145            case 2: /* x qpel, y halfpel - left or right during qpel refinement */
146                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
147                    ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth;
148                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
149                    break;
150    
151            default: /* pure halfpel position */
152                    return (uint8_t *) ref1;
153    
154            }
155            return Reference;
156    }
157    
158    uint8_t *
159    xvid_me_interpolate16x16qpel(const int x, const int y, const uint32_t dir, const SearchData * const data)
160    {
161            /* create or find a qpel-precision reference picture; return pointer to it */
162            uint8_t * Reference = data->RefQ + 16*dir;
163            const uint32_t iEdgedWidth = data->iEdgedWidth;
164            const uint32_t rounding = data->rounding;
165            const int halfpel_x = x/2;
166            const int halfpel_y = y/2;
167            const uint8_t *ref1, *ref2, *ref3, *ref4;
168    
169            ref1 = GetReferenceB(halfpel_x, halfpel_y, dir, data);
170            switch( ((x&1)<<1) + (y&1) ) {
171            case 3:
172                    /*
173                     * x and y in qpel resolution - the "corners" (top left/right and
174                     * bottom left/right) during qpel refinement
175                     */
176                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
177                    ref3 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
178                    ref4 = GetReferenceB(x - halfpel_x, y - halfpel_y, dir, data);
179                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
180                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
181                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
182                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
183                    break;
184    
185            case 1: /* x halfpel, y qpel - top or bottom during qpel refinement */
186                    ref2 = GetReferenceB(halfpel_x, y - halfpel_y, dir, data);
187                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
188                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
189                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
190                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
191                    break;
192    
193            case 2: /* x qpel, y halfpel - left or right during qpel refinement */
194                    ref2 = GetReferenceB(x - halfpel_x, halfpel_y, dir, data);
195                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8);
196                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8);
197                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8);
198                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8);
199                    break;
200    
201    
202            default: /* pure halfpel position */
203                    return (uint8_t *) ref1;
204            }
205            return Reference;
206    }
207    
208    void
209    xvid_me_AdvDiamondSearch(int x, int y, const SearchData * const data,
210                                                     int bDirection, CheckFunc * const CheckCandidate)
211    {
212    
213    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
214    
215            unsigned int * const iDirection = data->dir;
216    
217            for(;;) { /* forever */
218                    *iDirection = 0;
219                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
220                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
221                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
222                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
223    
224                    /* now we're doing diagonal checks near our candidate */
225    
226                    if (*iDirection) {              /* if anything found */
227                            bDirection = *iDirection;
228                            *iDirection = 0;
229                            x = data->currentMV->x; y = data->currentMV->y;
230                            if (bDirection & 3) {   /* our candidate is left or right */
231                                    CHECK_CANDIDATE(x, y + iDiamondSize, 8);
232                                    CHECK_CANDIDATE(x, y - iDiamondSize, 4);
233                            } else {                        /* what remains here is up or down */
234                                    CHECK_CANDIDATE(x + iDiamondSize, y, 2);
235                                    CHECK_CANDIDATE(x - iDiamondSize, y, 1);
236                            }
237    
238                            if (*iDirection) {
239                                    bDirection += *iDirection;
240                                    x = data->currentMV->x; y = data->currentMV->y;
241                            }
242                    } else {                                /* about to quit, eh? not so fast.... */
243                            switch (bDirection) {
244                            case 2:
245                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
246                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
247                                    break;
248                            case 1:
249                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
250                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
251                                    break;
252                            case 2 + 4:
253                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
254                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
255                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
256                                    break;
257                            case 4:
258                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
259                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
260                                    break;
261                            case 8:
262                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
263                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
264                                    break;
265                            case 1 + 4:
266                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
267                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
268                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
269                                    break;
270                            case 2 + 8:
271                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
272                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
273                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
274                                    break;
275                            case 1 + 8:
276                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
277                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
278                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
279                                    break;
280                            default:                /* 1+2+4+8 == we didn't find anything at all */
281                                    CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1 + 4);
282                                    CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1 + 8);
283                                    CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2 + 4);
284                                    CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2 + 8);
285                                    break;
286                            }
287                            if (!*iDirection) break;                /* ok, the end. really */
288                            bDirection = *iDirection;
289                            x = data->currentMV->x; y = data->currentMV->y;
290                    }
291            }
292    }
293    
294    void
295    xvid_me_SquareSearch(int x, int y, const SearchData * const data,
296                                             int bDirection, CheckFunc * const CheckCandidate)
297    {
298            unsigned int * const iDirection = data->dir;
299    
300            do {
301                    *iDirection = 0;
302                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1+16+64);
303                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2+32+128);
304                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4+16+32);
305                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8+64+128);
306                    if (bDirection & 16) CHECK_CANDIDATE(x - iDiamondSize, y - iDiamondSize, 1+4+16+32+64);
307                    if (bDirection & 32) CHECK_CANDIDATE(x + iDiamondSize, y - iDiamondSize, 2+4+16+32+128);
308                    if (bDirection & 64) CHECK_CANDIDATE(x - iDiamondSize, y + iDiamondSize, 1+8+16+64+128);
309                    if (bDirection & 128) CHECK_CANDIDATE(x + iDiamondSize, y + iDiamondSize, 2+8+32+64+128);
310    
311                    bDirection = *iDirection;
312                    x = data->currentMV->x; y = data->currentMV->y;
313            } while (*iDirection);
314    }
315    
316    void
317    xvid_me_DiamondSearch(int x, int y, const SearchData * const data,
318                                              int bDirection, CheckFunc * const CheckCandidate)
319    {
320    
321    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
322    
323            unsigned int * const iDirection = data->dir;
324    
325            do {
326                    *iDirection = 0;
327                    if (bDirection & 1) CHECK_CANDIDATE(x - iDiamondSize, y, 1);
328                    if (bDirection & 2) CHECK_CANDIDATE(x + iDiamondSize, y, 2);
329                    if (bDirection & 4) CHECK_CANDIDATE(x, y - iDiamondSize, 4);
330                    if (bDirection & 8) CHECK_CANDIDATE(x, y + iDiamondSize, 8);
331    
332                    /* now we're doing diagonal checks near our candidate */
333    
334                    if (*iDirection) {              /* checking if anything found */
335                            bDirection = *iDirection;
336                            *iDirection = 0;
337                            x = data->currentMV->x; y = data->currentMV->y;
338                            if (bDirection & 3) {   /* our candidate is left or right */
339                                    CHECK_CANDIDATE(x, y + iDiamondSize, 8);
340                                    CHECK_CANDIDATE(x, y - iDiamondSize, 4);
341                            } else {                        /* what remains here is up or down */
342                                    CHECK_CANDIDATE(x + iDiamondSize, y, 2);
343                                    CHECK_CANDIDATE(x - iDiamondSize, y, 1);
344                            }
345                            bDirection += *iDirection;
346                            x = data->currentMV->x; y = data->currentMV->y;
347                    }
348            }
349            while (*iDirection);
350    }
351    
352    void
353    xvid_me_SubpelRefine(const SearchData * const data, CheckFunc * const CheckCandidate)
354    {
355    /* Do a half-pel or q-pel refinement */
356            const VECTOR centerMV = data->qpel_precision ? *data->currentQMV : *data->currentMV;
357    
358            CHECK_CANDIDATE(centerMV.x, centerMV.y - 1, 0);
359            CHECK_CANDIDATE(centerMV.x + 1, centerMV.y - 1, 0);
360            CHECK_CANDIDATE(centerMV.x + 1, centerMV.y, 0);
361            CHECK_CANDIDATE(centerMV.x + 1, centerMV.y + 1, 0);
362            CHECK_CANDIDATE(centerMV.x, centerMV.y + 1, 0);
363            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y + 1, 0);
364            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y, 0);
365            CHECK_CANDIDATE(centerMV.x - 1, centerMV.y - 1, 0);
366    }
367    

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

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