[cvs] / xvidcore / src / prediction / mbprediction.h Repository:
ViewVC logotype

Annotation of /xvidcore/src/prediction/mbprediction.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.20 - (view) (download)

1 : edgomez 1.5 /**************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC
4 :     * - MB prediction header file -
5 :     *
6 : edgomez 1.19 * This program is an implementation of a part of one or more MPEG-4
7 :     * Video tools as specified in ISO/IEC 14496-2 standard. Those intending
8 :     * to use this software module in hardware or software products are
9 :     * advised that its use may infringe existing patents or copyrights, and
10 :     * any such use would be at such party's own risk. The original
11 :     * developer of this software module and his/her company, and subsequent
12 :     * editors and their companies, will have no liability for use of this
13 :     * software or modifications or derivatives thereof.
14 :     *
15 :     * This program is free software; you can redistribute it and/or modify
16 :     * it under the terms of the GNU General Public License as published by
17 :     * the xvid_free Software Foundation; either version 2 of the License, or
18 : edgomez 1.5 * (at your option) any later version.
19 :     *
20 :     * This program is distributed in the hope that it will be useful,
21 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 :     * GNU General Public License for more details.
24 :     *
25 :     * You should have received a copy of the GNU General Public License
26 : edgomez 1.19 * along with this program; if not, write to the xvid_free Software
27 :     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 : edgomez 1.5 *
29 : edgomez 1.20 * $Id: mbprediction.h,v 1.19 2003/02/15 15:22:19 edgomez Exp $
30 : edgomez 1.5 *
31 :     *************************************************************************/
32 :    
33 : edgomez 1.19 /******************************************************************************
34 :     * *
35 :     * Revision history: *
36 :     * *
37 :     * 29.06.2002 get_pmvdata() bounding *
38 :     * *
39 :     ******************************************************************************/
40 :    
41 :    
42 : Isibaar 1.1 #ifndef _MBPREDICTION_H_
43 :     #define _MBPREDICTION_H_
44 :    
45 :     #include "../portab.h"
46 :     #include "../decoder.h"
47 :     #include "../global.h"
48 :    
49 :     #define MIN(X, Y) ((X)<(Y)?(X):(Y))
50 :     #define MAX(X, Y) ((X)>(Y)?(X):(Y))
51 :    
52 : edgomez 1.5 /* very large value */
53 : Isibaar 1.1 #define MV_MAX_ERROR (4096 * 256)
54 :    
55 :     #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
56 :    
57 : edgomez 1.9 void MBPrediction(FRAMEINFO * frame, /* <-- The parameter for ACDC and MV prediction */
58 :    
59 :     uint32_t x_pos, /* <-- The x position of the MB to be searched */
60 :    
61 :     uint32_t y_pos, /* <-- The y position of the MB to be searched */
62 :    
63 :     uint32_t x_dim, /* <-- Number of macroblocks in a row */
64 :    
65 :     int16_t * qcoeff); /* <-> The quantized DCT coefficients */
66 :    
67 :     void add_acdc(MACROBLOCK * pMB,
68 :     uint32_t block,
69 :     int16_t dct_codes[64],
70 :     uint32_t iDcScaler,
71 :     int16_t predictors[8]);
72 :    
73 :    
74 :     void predict_acdc(MACROBLOCK * pMBs,
75 :     uint32_t x,
76 :     uint32_t y,
77 :     uint32_t mb_width,
78 :     uint32_t block,
79 :     int16_t qcoeff[64],
80 :     uint32_t current_quant,
81 :     int32_t iDcScaler,
82 : suxen_drol 1.10 int16_t predictors[8],
83 : suxen_drol 1.11 const int bound);
84 : suxen_drol 1.10
85 : Isibaar 1.1
86 : edgomez 1.19 #ifdef OLD_GETPMV
87 :     /* get_pmvdata returns the median predictor and nothing else */
88 :    
89 :     static __inline VECTOR
90 :     get_pmv(const MACROBLOCK * const pMBs,
91 :     const uint32_t x,
92 :     const uint32_t y,
93 :     const uint32_t x_dim,
94 :     const uint32_t block)
95 :     {
96 :    
97 :     int xin1, xin2, xin3;
98 :     int yin1, yin2, yin3;
99 :     int vec1, vec2, vec3;
100 :     VECTOR lneigh, tneigh, trneigh; /* left neighbour, top neighbour, topright neighbour */
101 :     VECTOR median;
102 :    
103 :     static VECTOR zeroMV = { 0, 0 };
104 :     uint32_t index = x + y * x_dim;
105 :    
106 :     /* first row (special case) */
107 :     if (y == 0 && (block == 0 || block == 1)) {
108 :     if ((x == 0) && (block == 0)) // first column, first block
109 :     {
110 :     return zeroMV;
111 :     }
112 :     if (block == 1) // second block; has only a left neighbour
113 :     {
114 :     return pMBs[index].mvs[0];
115 :     } else { /* block==0, but x!=0, so again, there is a left neighbour */
116 :    
117 :     return pMBs[index - 1].mvs[1];
118 :     }
119 :     }
120 :    
121 :     /*
122 :     * MODE_INTER, vm18 page 48
123 :     * MODE_INTER4V vm18 page 51
124 :     *
125 :     * (x,y-1) (x+1,y-1)
126 :     * [ | ] [ | ]
127 :     * [ 2 | 3 ] [ 2 | ]
128 :     *
129 :     * (x-1,y) (x,y) (x+1,y)
130 :     * [ | 1 ] [ 0 | 1 ] [ 0 | ]
131 :     * [ | 3 ] [ 2 | 3 ] [ | ]
132 :     */
133 :    
134 :     switch (block) {
135 :     case 0:
136 :     xin1 = x - 1;
137 :     yin1 = y;
138 :     vec1 = 1; /* left */
139 :     xin2 = x;
140 :     yin2 = y - 1;
141 :     vec2 = 2; /* top */
142 :     xin3 = x + 1;
143 :     yin3 = y - 1;
144 :     vec3 = 2; /* top right */
145 :     break;
146 :     case 1:
147 :     xin1 = x;
148 :     yin1 = y;
149 :     vec1 = 0;
150 :     xin2 = x;
151 :     yin2 = y - 1;
152 :     vec2 = 3;
153 :     xin3 = x + 1;
154 :     yin3 = y - 1;
155 :     vec3 = 2;
156 :     break;
157 :     case 2:
158 :     xin1 = x - 1;
159 :     yin1 = y;
160 :     vec1 = 3;
161 :     xin2 = x;
162 :     yin2 = y;
163 :     vec2 = 0;
164 :     xin3 = x;
165 :     yin3 = y;
166 :     vec3 = 1;
167 :     break;
168 :     default:
169 :     xin1 = x;
170 :     yin1 = y;
171 :     vec1 = 2;
172 :     xin2 = x;
173 :     yin2 = y;
174 :     vec2 = 0;
175 :     xin3 = x;
176 :     yin3 = y;
177 :     vec3 = 1;
178 :     }
179 :    
180 :    
181 :     if (xin1 < 0 || /* yin1 < 0 || */ xin1 >= (int32_t) x_dim) {
182 :     lneigh = zeroMV;
183 :     } else {
184 :     lneigh = pMBs[xin1 + yin1 * x_dim].mvs[vec1];
185 :     }
186 :    
187 :     if (xin2 < 0 || /* yin2 < 0 || */ xin2 >= (int32_t) x_dim) {
188 :     tneigh = zeroMV;
189 :     } else {
190 :     tneigh = pMBs[xin2 + yin2 * x_dim].mvs[vec2];
191 :     }
192 :    
193 :     if (xin3 < 0 || /* yin3 < 0 || */ xin3 >= (int32_t) x_dim) {
194 :     trneigh = zeroMV;
195 :     } else {
196 :     trneigh = pMBs[xin3 + yin3 * x_dim].mvs[vec3];
197 :     }
198 :    
199 :     /* median,minimum */
200 :    
201 :     median.x =
202 :     MIN(MAX(lneigh.x, tneigh.x),
203 :     MIN(MAX(tneigh.x, trneigh.x), MAX(lneigh.x, trneigh.x)));
204 :     median.y =
205 :     MIN(MAX(lneigh.y, tneigh.y),
206 :     MIN(MAX(tneigh.y, trneigh.y), MAX(lneigh.y, trneigh.y)));
207 :     return median;
208 :     }
209 :    
210 :    
211 :     static __inline VECTOR
212 :     get_qpmv(const MACROBLOCK * const pMBs,
213 :     const uint32_t x,
214 :     const uint32_t y,
215 :     const uint32_t x_dim,
216 :     const uint32_t block)
217 :     {
218 :    
219 :     int xin1, xin2, xin3;
220 :     int yin1, yin2, yin3;
221 :     int vec1, vec2, vec3;
222 :     VECTOR lneigh, tneigh, trneigh; /* left neighbour, top neighbour, topright neighbour */
223 :     VECTOR median;
224 :    
225 :     static VECTOR zeroMV = { 0, 0 };
226 :     uint32_t index = x + y * x_dim;
227 :    
228 :     /* first row (special case) */
229 :     if (y == 0 && (block == 0 || block == 1)) {
230 :     if ((x == 0) && (block == 0)) // first column, first block
231 :     {
232 :     return zeroMV;
233 :     }
234 :     if (block == 1) // second block; has only a left neighbour
235 :     {
236 :     return pMBs[index].qmvs[0];
237 :     } else { /* block==0, but x!=0, so again, there is a left neighbour */
238 :    
239 :     return pMBs[index - 1].qmvs[1];
240 :     }
241 :     }
242 :    
243 :     /*
244 :     * MODE_INTER, vm18 page 48
245 :     * MODE_INTER4V vm18 page 51
246 :     *
247 :     * (x,y-1) (x+1,y-1)
248 :     * [ | ] [ | ]
249 :     * [ 2 | 3 ] [ 2 | ]
250 :     *
251 :     * (x-1,y) (x,y) (x+1,y)
252 :     * [ | 1 ] [ 0 | 1 ] [ 0 | ]
253 :     * [ | 3 ] [ 2 | 3 ] [ | ]
254 :     */
255 :    
256 :     switch (block) {
257 :     case 0:
258 :     xin1 = x - 1;
259 :     yin1 = y;
260 :     vec1 = 1; /* left */
261 :     xin2 = x;
262 :     yin2 = y - 1;
263 :     vec2 = 2; /* top */
264 :     xin3 = x + 1;
265 :     yin3 = y - 1;
266 :     vec3 = 2; /* top right */
267 :     break;
268 :     case 1:
269 :     xin1 = x;
270 :     yin1 = y;
271 :     vec1 = 0;
272 :     xin2 = x;
273 :     yin2 = y - 1;
274 :     vec2 = 3;
275 :     xin3 = x + 1;
276 :     yin3 = y - 1;
277 :     vec3 = 2;
278 :     break;
279 :     case 2:
280 :     xin1 = x - 1;
281 :     yin1 = y;
282 :     vec1 = 3;
283 :     xin2 = x;
284 :     yin2 = y;
285 :     vec2 = 0;
286 :     xin3 = x;
287 :     yin3 = y;
288 :     vec3 = 1;
289 :     break;
290 :     default:
291 :     xin1 = x;
292 :     yin1 = y;
293 :     vec1 = 2;
294 :     xin2 = x;
295 :     yin2 = y;
296 :     vec2 = 0;
297 :     xin3 = x;
298 :     yin3 = y;
299 :     vec3 = 1;
300 :     }
301 :    
302 :    
303 :     if (xin1 < 0 || /* yin1 < 0 || */ xin1 >= (int32_t) x_dim) {
304 :     lneigh = zeroMV;
305 :     } else {
306 :     lneigh = pMBs[xin1 + yin1 * x_dim].qmvs[vec1];
307 :     }
308 :    
309 :     if (xin2 < 0 || /* yin2 < 0 || */ xin2 >= (int32_t) x_dim) {
310 :     tneigh = zeroMV;
311 :     } else {
312 :     tneigh = pMBs[xin2 + yin2 * x_dim].qmvs[vec2];
313 :     }
314 :    
315 :     if (xin3 < 0 || /* yin3 < 0 || */ xin3 >= (int32_t) x_dim) {
316 :     trneigh = zeroMV;
317 :     } else {
318 :     trneigh = pMBs[xin3 + yin3 * x_dim].qmvs[vec3];
319 :     }
320 :    
321 :     /* median,minimum */
322 :    
323 :     median.x =
324 :     MIN(MAX(lneigh.x, tneigh.x),
325 :     MIN(MAX(tneigh.x, trneigh.x), MAX(lneigh.x, trneigh.x)));
326 :     median.y =
327 :     MIN(MAX(lneigh.y, tneigh.y),
328 :     MIN(MAX(tneigh.y, trneigh.y), MAX(lneigh.y, trneigh.y)));
329 :     return median;
330 :     }
331 :    
332 :     /* This is somehow a copy of get_pmv, but returning all MVs and Minimum SAD
333 :     instead of only Median MV */
334 :    
335 :     static __inline int
336 :     get_pmvdata(const MACROBLOCK * const pMBs,
337 :     const uint32_t x,
338 :     const uint32_t y,
339 :     const uint32_t x_dim,
340 :     const uint32_t block,
341 :     VECTOR * const pmv,
342 :     int32_t * const psad)
343 :     {
344 :    
345 :     /*
346 :     * pmv are filled with:
347 :     * [0]: Median (or whatever is correct in a special case)
348 :     * [1]: left neighbour
349 :     * [2]: top neighbour
350 :     * [3]: topright neighbour
351 :     * psad are filled with:
352 :     * [0]: minimum of [1] to [3]
353 :     * [1]: left neighbour's SAD (NB:[1] to [3] are actually not needed)
354 :     * [2]: top neighbour's SAD
355 :     * [3]: topright neighbour's SAD
356 :     */
357 :    
358 :     int xin1, xin2, xin3;
359 :     int yin1, yin2, yin3;
360 :     int vec1, vec2, vec3;
361 :    
362 :     uint32_t index = x + y * x_dim;
363 :     const VECTOR zeroMV = { 0, 0 };
364 :    
365 :     // first row of blocks (special case)
366 :     if (y == 0 && (block == 0 || block == 1)) {
367 :     if ((x == 0) && (block == 0)) // first column, first block
368 :     {
369 :     pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
370 :     psad[0] = 0;
371 :     psad[1] = psad[2] = psad[3] = MV_MAX_ERROR;
372 :     return 0;
373 :     }
374 :     if (block == 1) // second block; has only a left neighbour
375 :     {
376 :     pmv[0] = pmv[1] = pMBs[index].mvs[0];
377 :     pmv[2] = pmv[3] = zeroMV;
378 :     psad[0] = psad[1] = pMBs[index].sad8[0];
379 :     psad[2] = psad[3] = MV_MAX_ERROR;
380 :     return 0;
381 :     } else { /* block==0, but x!=0, so again, there is a left neighbour */
382 :    
383 :     pmv[0] = pmv[1] = pMBs[index - 1].mvs[1];
384 :     pmv[2] = pmv[3] = zeroMV;
385 :     psad[0] = psad[1] = pMBs[index - 1].sad8[1];
386 :     psad[2] = psad[3] = MV_MAX_ERROR;
387 :     return 0;
388 :     }
389 :     }
390 :    
391 :     /*
392 :     * MODE_INTER, vm18 page 48
393 :     * MODE_INTER4V vm18 page 51
394 :     *
395 :     * (x,y-1) (x+1,y-1)
396 :     * [ | ] [ | ]
397 :     * [ 2 | 3 ] [ 2 | ]
398 :     *
399 :     * (x-1,y) (x,y) (x+1,y)
400 :     * [ | 1 ] [ 0 | 1 ] [ 0 | ]
401 :     * [ | 3 ] [ 2 | 3 ] [ | ]
402 :     */
403 :    
404 :     switch (block) {
405 :     case 0:
406 :     xin1 = x - 1;
407 :     yin1 = y;
408 :     vec1 = 1; /* left */
409 :     xin2 = x;
410 :     yin2 = y - 1;
411 :     vec2 = 2; /* top */
412 :     xin3 = x + 1;
413 :     yin3 = y - 1;
414 :     vec3 = 2; /* top right */
415 :     break;
416 :     case 1:
417 :     xin1 = x;
418 :     yin1 = y;
419 :     vec1 = 0;
420 :     xin2 = x;
421 :     yin2 = y - 1;
422 :     vec2 = 3;
423 :     xin3 = x + 1;
424 :     yin3 = y - 1;
425 :     vec3 = 2;
426 :     break;
427 :     case 2:
428 :     xin1 = x - 1;
429 :     yin1 = y;
430 :     vec1 = 3;
431 :     xin2 = x;
432 :     yin2 = y;
433 :     vec2 = 0;
434 :     xin3 = x;
435 :     yin3 = y;
436 :     vec3 = 1;
437 :     break;
438 :     default:
439 :     xin1 = x;
440 :     yin1 = y;
441 :     vec1 = 2;
442 :     xin2 = x;
443 :     yin2 = y;
444 :     vec2 = 0;
445 :     xin3 = x;
446 :     yin3 = y;
447 :     vec3 = 1;
448 :     }
449 :    
450 :    
451 :     if (xin1 < 0 || xin1 >= (int32_t) x_dim) {
452 :     pmv[1] = zeroMV;
453 :     psad[1] = MV_MAX_ERROR;
454 :     } else {
455 :     pmv[1] = pMBs[xin1 + yin1 * x_dim].mvs[vec1];
456 :     psad[1] = pMBs[xin1 + yin1 * x_dim].sad8[vec1];
457 :     }
458 :    
459 :     if (xin2 < 0 || xin2 >= (int32_t) x_dim) {
460 :     pmv[2] = zeroMV;
461 :     psad[2] = MV_MAX_ERROR;
462 :     } else {
463 :     pmv[2] = pMBs[xin2 + yin2 * x_dim].mvs[vec2];
464 :     psad[2] = pMBs[xin2 + yin2 * x_dim].sad8[vec2];
465 :     }
466 :    
467 :     if (xin3 < 0 || xin3 >= (int32_t) x_dim) {
468 :     pmv[3] = zeroMV;
469 :     psad[3] = MV_MAX_ERROR;
470 :     } else {
471 :     pmv[3] = pMBs[xin3 + yin3 * x_dim].mvs[vec3];
472 :     psad[3] = pMBs[xin3 + yin3 * x_dim].sad8[vec3];
473 :     }
474 :    
475 :     if ((MVequal(pmv[1], pmv[2])) && (MVequal(pmv[1], pmv[3]))) {
476 :     pmv[0] = pmv[1];
477 :     psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]);
478 :     return 1;
479 :     }
480 :    
481 :     /* median,minimum */
482 :    
483 :     pmv[0].x =
484 :     MIN(MAX(pmv[1].x, pmv[2].x),
485 :     MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
486 :     pmv[0].y =
487 :     MIN(MAX(pmv[1].y, pmv[2].y),
488 :     MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
489 :     psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]);
490 :    
491 :     return 0;
492 :     }
493 :    
494 :     #endif
495 :    
496 :     /*
497 :     * MODE_INTER, vm18 page 48
498 :     * MODE_INTER4V vm18 page 51
499 :     *
500 :     * (x,y-1) (x+1,y-1)
501 :     * [ | ] [ | ]
502 :     * [ 2 | 3 ] [ 2 | ]
503 :     *
504 :     * (x-1,y) (x,y) (x+1,y)
505 :     * [ | 1 ] [ 0 | 1 ] [ 0 | ]
506 :     * [ | 3 ] [ 2 | 3 ] [ | ]
507 :     */
508 : suxen_drol 1.12
509 :     static __inline VECTOR
510 :     get_pmv2(const MACROBLOCK * const mbs,
511 :     const int mb_width,
512 :     const int bound,
513 :     const int x,
514 :     const int y,
515 :     const int block)
516 :     {
517 :     static const VECTOR zeroMV = { 0, 0 };
518 :    
519 :     int lx, ly, lz; /* left */
520 :     int tx, ty, tz; /* top */
521 :     int rx, ry, rz; /* top-right */
522 :     int lpos, tpos, rpos;
523 :     int num_cand, last_cand;
524 :    
525 :     VECTOR pmv[4]; /* left neighbour, top neighbour, top-right neighbour */
526 :    
527 :     switch (block) {
528 :     case 0:
529 :     lx = x - 1; ly = y; lz = 1;
530 :     tx = x; ty = y - 1; tz = 2;
531 :     rx = x + 1; ry = y - 1; rz = 2;
532 :     break;
533 :     case 1:
534 :     lx = x; ly = y; lz = 0;
535 :     tx = x; ty = y - 1; tz = 3;
536 :     rx = x + 1; ry = y - 1; rz = 2;
537 :     break;
538 :     case 2:
539 :     lx = x - 1; ly = y; lz = 3;
540 :     tx = x; ty = y; tz = 0;
541 :     rx = x; ry = y; rz = 1;
542 :     break;
543 :     default:
544 :     lx = x; ly = y; lz = 2;
545 :     tx = x; ty = y; tz = 0;
546 :     rx = x; ry = y; rz = 1;
547 :     }
548 :    
549 :     lpos = lx + ly * mb_width;
550 :     rpos = rx + ry * mb_width;
551 :     tpos = tx + ty * mb_width;
552 : edgomez 1.20 last_cand = num_cand = 0;
553 : suxen_drol 1.12
554 :     if (lpos >= bound && lx >= 0) {
555 :     num_cand++;
556 :     last_cand = 1;
557 :     pmv[1] = mbs[lpos].mvs[lz];
558 :     } else {
559 :     pmv[1] = zeroMV;
560 :     }
561 :    
562 :     if (tpos >= bound) {
563 :     num_cand++;
564 :     last_cand = 2;
565 :     pmv[2] = mbs[tpos].mvs[tz];
566 :     } else {
567 :     pmv[2] = zeroMV;
568 :     }
569 :    
570 :     if (rpos >= bound && rx < mb_width) {
571 :     num_cand++;
572 :     last_cand = 3;
573 :     pmv[3] = mbs[rpos].mvs[rz];
574 :     } else {
575 :     pmv[3] = zeroMV;
576 :     }
577 :    
578 : edgomez 1.20 /*
579 :     * If there're more than one candidate, we return the median vector
580 :     * edgomez : the special case "no candidates" is handled the same way
581 :     * because all vectors are set to zero. So the median vector
582 :     * is {0,0}, and this is exactly the vector we must return
583 :     * according to the mpeg4 specs.
584 :     */
585 : edgomez 1.19 if (num_cand != 1) {
586 :     /* set median */
587 :    
588 :     pmv[0].x =
589 :     MIN(MAX(pmv[1].x, pmv[2].x),
590 :     MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
591 :     pmv[0].y =
592 :     MIN(MAX(pmv[1].y, pmv[2].y),
593 :     MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
594 :     return pmv[0];
595 :     }
596 :    
597 :     return pmv[last_cand]; /* no point calculating median mv */
598 :     }
599 :    
600 :    
601 :    
602 :     /*
603 :     * MODE_INTER, vm18 page 48
604 :     * MODE_INTER4V vm18 page 51
605 :     *
606 :     * (x,y-1) (x+1,y-1)
607 :     * [ | ] [ | ]
608 :     * [ 2 | 3 ] [ 2 | ]
609 :     *
610 :     * (x-1,y) (x,y) (x+1,y)
611 :     * [ | 1 ] [ 0 | 1 ] [ 0 | ]
612 :     * [ | 3 ] [ 2 | 3 ] [ | ]
613 : edgomez 1.15 */
614 :    
615 : edgomez 1.19 static __inline VECTOR
616 :     get_qpmv2(const MACROBLOCK * const mbs,
617 :     const int mb_width,
618 :     const int bound,
619 :     const int x,
620 :     const int y,
621 :     const int block)
622 :     {
623 :     static const VECTOR zeroMV = { 0, 0 };
624 :    
625 :     int lx, ly, lz; /* left */
626 :     int tx, ty, tz; /* top */
627 :     int rx, ry, rz; /* top-right */
628 :     int lpos, tpos, rpos;
629 :     int num_cand, last_cand;
630 :    
631 :     VECTOR pmv[4]; /* left neighbour, top neighbour, top-right neighbour */
632 :    
633 :     switch (block) {
634 :     case 0:
635 :     lx = x - 1; ly = y; lz = 1;
636 :     tx = x; ty = y - 1; tz = 2;
637 :     rx = x + 1; ry = y - 1; rz = 2;
638 :     break;
639 :     case 1:
640 :     lx = x; ly = y; lz = 0;
641 :     tx = x; ty = y - 1; tz = 3;
642 :     rx = x + 1; ry = y - 1; rz = 2;
643 :     break;
644 :     case 2:
645 :     lx = x - 1; ly = y; lz = 3;
646 :     tx = x; ty = y; tz = 0;
647 :     rx = x; ry = y; rz = 1;
648 :     break;
649 :     default:
650 :     lx = x; ly = y; lz = 2;
651 :     tx = x; ty = y; tz = 0;
652 :     rx = x; ry = y; rz = 1;
653 :     }
654 :    
655 :     lpos = lx + ly * mb_width;
656 :     rpos = rx + ry * mb_width;
657 :     tpos = tx + ty * mb_width;
658 : edgomez 1.20 last_cand = num_cand = 0;
659 : edgomez 1.19
660 :     if (lpos >= bound && lx >= 0) {
661 :     num_cand++;
662 :     last_cand = 1;
663 :     pmv[1] = mbs[lpos].qmvs[lz];
664 :     } else {
665 :     pmv[1] = zeroMV;
666 :     }
667 :    
668 :     if (tpos >= bound) {
669 :     num_cand++;
670 :     last_cand = 2;
671 :     pmv[2] = mbs[tpos].qmvs[tz];
672 :     } else {
673 :     pmv[2] = zeroMV;
674 :     }
675 :    
676 :     if (rpos >= bound && rx < mb_width) {
677 :     num_cand++;
678 :     last_cand = 3;
679 :     pmv[3] = mbs[rpos].qmvs[rz];
680 :     } else {
681 :     pmv[3] = zeroMV;
682 :     }
683 :    
684 : edgomez 1.20 /*
685 :     * If there're more than one candidate, we return the median vector
686 :     * edgomez : the special case "no candidates" is handled the same way
687 :     * because all vectors are set to zero. So the median vector
688 :     * is {0,0}, and this is exactly the vector we must return
689 :     * according to the mpeg4 specs.
690 :     */
691 : suxen_drol 1.12 if (num_cand != 1) {
692 :     /* set median */
693 :    
694 :     pmv[0].x =
695 :     MIN(MAX(pmv[1].x, pmv[2].x),
696 :     MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
697 :     pmv[0].y =
698 :     MIN(MAX(pmv[1].y, pmv[2].y),
699 :     MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
700 :     return pmv[0];
701 :     }
702 :    
703 :     return pmv[last_cand]; /* no point calculating median mv */
704 :     }
705 :    
706 :    
707 : edgomez 1.19 /*
708 :     * pmv are filled with:
709 :     * [0]: Median (or whatever is correct in a special case)
710 :     * [1]: left neighbour
711 :     * [2]: top neighbour
712 :     * [3]: topright neighbour
713 :     * psad are filled with:
714 :     * [0]: minimum of [1] to [3]
715 :     * [1]: left neighbour's SAD (NB:[1] to [3] are actually not needed)
716 :     * [2]: top neighbour's SAD
717 :     * [3]: topright neighbour's SAD
718 :     */
719 : chl 1.13
720 : suxen_drol 1.12 static __inline int
721 :     get_pmvdata2(const MACROBLOCK * const mbs,
722 :     const int mb_width,
723 :     const int bound,
724 :     const int x,
725 :     const int y,
726 :     const int block,
727 :     VECTOR * const pmv,
728 :     int32_t * const psad)
729 :     {
730 :     static const VECTOR zeroMV = { 0, 0 };
731 :    
732 :     int lx, ly, lz; /* left */
733 :     int tx, ty, tz; /* top */
734 :     int rx, ry, rz; /* top-right */
735 :     int lpos, tpos, rpos;
736 :     int num_cand, last_cand;
737 :    
738 :     switch (block) {
739 :     case 0:
740 :     lx = x - 1; ly = y; lz = 1;
741 :     tx = x; ty = y - 1; tz = 2;
742 :     rx = x + 1; ry = y - 1; rz = 2;
743 :     break;
744 :     case 1:
745 :     lx = x; ly = y; lz = 0;
746 :     tx = x; ty = y - 1; tz = 3;
747 :     rx = x + 1; ry = y - 1; rz = 2;
748 :     break;
749 :     case 2:
750 :     lx = x - 1; ly = y; lz = 3;
751 :     tx = x; ty = y; tz = 0;
752 :     rx = x; ry = y; rz = 1;
753 :     break;
754 :     default:
755 :     lx = x; ly = y; lz = 2;
756 :     tx = x; ty = y; tz = 0;
757 :     rx = x; ry = y; rz = 1;
758 :     }
759 :    
760 :     lpos = lx + ly * mb_width;
761 :     rpos = rx + ry * mb_width;
762 :     tpos = tx + ty * mb_width;
763 : edgomez 1.20 last_cand = num_cand = 0;
764 : suxen_drol 1.12
765 :     if (lpos >= bound && lx >= 0) {
766 :     num_cand++;
767 :     last_cand = 1;
768 :     pmv[1] = mbs[lpos].mvs[lz];
769 :     psad[1] = mbs[lpos].sad8[lz];
770 :     } else {
771 :     pmv[1] = zeroMV;
772 :     psad[1] = MV_MAX_ERROR;
773 :     }
774 :    
775 :     if (tpos >= bound) {
776 :     num_cand++;
777 :     last_cand = 2;
778 :     pmv[2]= mbs[tpos].mvs[tz];
779 :     psad[2] = mbs[tpos].sad8[tz];
780 :     } else {
781 :     pmv[2] = zeroMV;
782 :     psad[2] = MV_MAX_ERROR;
783 :     }
784 :    
785 :     if (rpos >= bound && rx < mb_width) {
786 :     num_cand++;
787 :     last_cand = 3;
788 :     pmv[3] = mbs[rpos].mvs[rz];
789 :     psad[3] = mbs[rpos].sad8[rz];
790 : chl 1.13 } else {
791 :     pmv[3] = zeroMV;
792 :     psad[3] = MV_MAX_ERROR;
793 :     }
794 :    
795 :     /* original pmvdata() compatibility hack */
796 :     if (x == 0 && y == 0 && block == 0)
797 :     {
798 :     pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
799 :     psad[0] = 0;
800 :     psad[1] = psad[2] = psad[3] = MV_MAX_ERROR;
801 :     return 0;
802 :     }
803 :    
804 :     /* if only one valid candidate preictor, the invalid candiates are set to the canidate */
805 :     if (num_cand == 1) {
806 :     pmv[0] = pmv[last_cand];
807 :     psad[0] = psad[last_cand];
808 : edgomez 1.19 // return MVequal(pmv[0], zeroMV); /* no point calculating median mv and minimum sad */
809 : chl 1.13
810 :     /* original pmvdata() compatibility hack */
811 :     return y==0 && block <= 1 ? 0 : MVequal(pmv[0], zeroMV);
812 :     }
813 :    
814 :     if ((MVequal(pmv[1], pmv[2])) && (MVequal(pmv[1], pmv[3]))) {
815 :     pmv[0] = pmv[1];
816 :     psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]);
817 :     return 1;
818 :     /* compatibility patch */
819 : edgomez 1.19 //return y==0 && block <= 1 ? 0 : 1;
820 : chl 1.13 }
821 :    
822 :     /* set median, minimum */
823 :    
824 :     pmv[0].x =
825 :     MIN(MAX(pmv[1].x, pmv[2].x),
826 :     MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
827 :     pmv[0].y =
828 :     MIN(MAX(pmv[1].y, pmv[2].y),
829 :     MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
830 :    
831 :     psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]);
832 :    
833 :     return 0;
834 :     }
835 :    
836 :     /* copies of get_pmv and get_pmvdata for prediction from integer search */
837 :    
838 :     static __inline VECTOR
839 :     get_ipmv(const MACROBLOCK * const mbs,
840 :     const int mb_width,
841 :     const int bound,
842 :     const int x,
843 :     const int y,
844 :     const int block)
845 :     {
846 :     static const VECTOR zeroMV = { 0, 0 };
847 :    
848 :     int lx, ly, lz; /* left */
849 :     int tx, ty, tz; /* top */
850 :     int rx, ry, rz; /* top-right */
851 :     int lpos, tpos, rpos;
852 :     int num_cand, last_cand;
853 :    
854 :     VECTOR pmv[4]; /* left neighbour, top neighbour, top-right neighbour */
855 :    
856 :     switch (block) {
857 :     case 0:
858 :     lx = x - 1; ly = y; lz = 1;
859 :     tx = x; ty = y - 1; tz = 2;
860 :     rx = x + 1; ry = y - 1; rz = 2;
861 :     break;
862 :     case 1:
863 :     lx = x; ly = y; lz = 0;
864 :     tx = x; ty = y - 1; tz = 3;
865 :     rx = x + 1; ry = y - 1; rz = 2;
866 :     break;
867 :     case 2:
868 :     lx = x - 1; ly = y; lz = 3;
869 :     tx = x; ty = y; tz = 0;
870 :     rx = x; ry = y; rz = 1;
871 :     break;
872 :     default:
873 :     lx = x; ly = y; lz = 2;
874 :     tx = x; ty = y; tz = 0;
875 :     rx = x; ry = y; rz = 1;
876 :     }
877 :    
878 :     lpos = lx + ly * mb_width;
879 :     rpos = rx + ry * mb_width;
880 :     tpos = tx + ty * mb_width;
881 : edgomez 1.19 num_cand = 0;
882 : chl 1.13
883 :     if (lpos >= bound && lx >= 0) {
884 :     num_cand++;
885 :     last_cand = 1;
886 :     pmv[1] = mbs[lpos].i_mvs[lz];
887 :     } else {
888 :     pmv[1] = zeroMV;
889 :     }
890 :    
891 :     if (tpos >= bound) {
892 :     num_cand++;
893 :     last_cand = 2;
894 :     pmv[2] = mbs[tpos].i_mvs[tz];
895 :     } else {
896 :     pmv[2] = zeroMV;
897 :     }
898 :    
899 :     if (rpos >= bound && rx < mb_width) {
900 :     num_cand++;
901 :     last_cand = 3;
902 :     pmv[3] = mbs[rpos].i_mvs[rz];
903 :     } else {
904 :     pmv[3] = zeroMV;
905 :     }
906 :    
907 :     /* if only one valid candidate predictor, the invalid candiates are set to the canidate */
908 :     if (num_cand != 1) {
909 :     /* set median */
910 :    
911 :     pmv[0].x =
912 :     MIN(MAX(pmv[1].x, pmv[2].x),
913 :     MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
914 :     pmv[0].y =
915 :     MIN(MAX(pmv[1].y, pmv[2].y),
916 :     MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
917 :     return pmv[0];
918 :     }
919 :    
920 :     return pmv[last_cand]; /* no point calculating median mv */
921 :     }
922 :    
923 :     static __inline int
924 :     get_ipmvdata(const MACROBLOCK * const mbs,
925 :     const int mb_width,
926 :     const int bound,
927 :     const int x,
928 :     const int y,
929 :     const int block,
930 :     VECTOR * const pmv,
931 :     int32_t * const psad)
932 :     {
933 :     static const VECTOR zeroMV = { 0, 0 };
934 :    
935 :     int lx, ly, lz; /* left */
936 :     int tx, ty, tz; /* top */
937 :     int rx, ry, rz; /* top-right */
938 :     int lpos, tpos, rpos;
939 :     int num_cand, last_cand;
940 :    
941 :     switch (block) {
942 :     case 0:
943 :     lx = x - 1; ly = y; lz = 1;
944 :     tx = x; ty = y - 1; tz = 2;
945 :     rx = x + 1; ry = y - 1; rz = 2;
946 :     break;
947 :     case 1:
948 :     lx = x; ly = y; lz = 0;
949 :     tx = x; ty = y - 1; tz = 3;
950 :     rx = x + 1; ry = y - 1; rz = 2;
951 :     break;
952 :     case 2:
953 :     lx = x - 1; ly = y; lz = 3;
954 :     tx = x; ty = y; tz = 0;
955 :     rx = x; ry = y; rz = 1;
956 :     break;
957 :     default:
958 :     lx = x; ly = y; lz = 2;
959 :     tx = x; ty = y; tz = 0;
960 :     rx = x; ry = y; rz = 1;
961 :     }
962 :    
963 :     lpos = lx + ly * mb_width;
964 :     rpos = rx + ry * mb_width;
965 :     tpos = tx + ty * mb_width;
966 : edgomez 1.19 num_cand = 0;
967 : chl 1.13
968 :     if (lpos >= bound && lx >= 0) {
969 :     num_cand++;
970 :     last_cand = 1;
971 :     pmv[1] = mbs[lpos].i_mvs[lz];
972 :     psad[1] = mbs[lpos].i_sad8[lz];
973 :     } else {
974 :     pmv[1] = zeroMV;
975 :     psad[1] = MV_MAX_ERROR;
976 :     }
977 :    
978 :     if (tpos >= bound) {
979 :     num_cand++;
980 :     last_cand = 2;
981 :     pmv[2]= mbs[tpos].i_mvs[tz];
982 :     psad[2] = mbs[tpos].i_sad8[tz];
983 :     } else {
984 :     pmv[2] = zeroMV;
985 :     psad[2] = MV_MAX_ERROR;
986 :     }
987 :    
988 :     if (rpos >= bound && rx < mb_width) {
989 :     num_cand++;
990 :     last_cand = 3;
991 :     pmv[3] = mbs[rpos].i_mvs[rz];
992 :     psad[3] = mbs[rpos].i_sad8[rz];
993 : suxen_drol 1.12 } else {
994 :     pmv[3] = zeroMV;
995 :     psad[3] = MV_MAX_ERROR;
996 :     }
997 :    
998 :     /* original pmvdata() compatibility hack */
999 :     if (x == 0 && y == 0 && block == 0)
1000 :     {
1001 :     pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
1002 :     psad[0] = 0;
1003 :     psad[1] = psad[2] = psad[3] = MV_MAX_ERROR;
1004 :     return 0;
1005 :     }
1006 :    
1007 :     /* if only one valid candidate preictor, the invalid candiates are set to the canidate */
1008 :     if (num_cand == 1) {
1009 :     pmv[0] = pmv[last_cand];
1010 :     psad[0] = psad[last_cand];
1011 : edgomez 1.19 // return MVequal(pmv[0], zeroMV); /* no point calculating median mv and minimum sad */
1012 : suxen_drol 1.12
1013 :     /* original pmvdata() compatibility hack */
1014 :     return y==0 && block <= 1 ? 0 : MVequal(pmv[0], zeroMV);
1015 :     }
1016 :    
1017 :     if ((MVequal(pmv[1], pmv[2])) && (MVequal(pmv[1], pmv[3]))) {
1018 :     pmv[0] = pmv[1];
1019 :     psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]);
1020 :     return 1;
1021 :     /* compatibility patch */
1022 : edgomez 1.19 //return y==0 && block <= 1 ? 0 : 1;
1023 : suxen_drol 1.12 }
1024 :    
1025 :     /* set median, minimum */
1026 :    
1027 :     pmv[0].x =
1028 :     MIN(MAX(pmv[1].x, pmv[2].x),
1029 :     MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
1030 :     pmv[0].y =
1031 :     MIN(MAX(pmv[1].y, pmv[2].y),
1032 :     MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
1033 :    
1034 :     psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]);
1035 :    
1036 :     return 0;
1037 :     }
1038 : Isibaar 1.1
1039 :    
1040 : edgomez 1.9 #endif /* _MBPREDICTION_H_ */

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