ffmpeg / libavcodec / motion_est.c @ 174489bd
History  View  Annotate  Download (20.8 KB)
1 
/*


2 
* Motion estimation

3 
* Copyright (c) 2000,2001 Gerard Lantau.

4 
*

5 
*

6 
* This program is free software; you can redistribute it and/or modify

7 
* it under the terms of the GNU General Public License as published by

8 
* the Free Software Foundation; either version 2 of the License, or

9 
* (at your option) any later version.

10 
*

11 
* This program is distributed in the hope that it will be useful,

12 
* but WITHOUT ANY WARRANTY; without even the implied warranty of

13 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

14 
* GNU General Public License for more details.

15 
*

16 
* You should have received a copy of the GNU General Public License

17 
* along with this program; if not, write to the Free Software

18 
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

19 
*

20 
* new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>

21 
*/

22 
#include <stdlib.h> 
23 
#include <stdio.h> 
24 
#include "avcodec.h" 
25 
#include "dsputil.h" 
26 
#include "mpegvideo.h" 
27  
28 
#define ABS(a) ((a)>0 ? (a) : (a)) 
29 
#define INTER_BIAS 257 
30  
31 
static void halfpel_motion_search(MpegEncContext * s, 
32 
int *mx_ptr, int *my_ptr, int dmin, 
33 
int xmin, int ymin, int xmax, int ymax, 
34 
int pred_x, int pred_y); 
35  
36 
/* config it to test motion vector encoding (send random vectors) */

37 
//#define CONFIG_TEST_MV_ENCODE

38  
39 
static int pix_sum(UINT8 * pix, int line_size) 
40 
{ 
41 
int s, i, j;

42  
43 
s = 0;

44 
for (i = 0; i < 16; i++) { 
45 
for (j = 0; j < 16; j += 8) { 
46 
s += pix[0];

47 
s += pix[1];

48 
s += pix[2];

49 
s += pix[3];

50 
s += pix[4];

51 
s += pix[5];

52 
s += pix[6];

53 
s += pix[7];

54 
pix += 8;

55 
} 
56 
pix += line_size  16;

57 
} 
58 
return s;

59 
} 
60  
61 
static int pix_dev(UINT8 * pix, int line_size, int mean) 
62 
{ 
63 
int s, i, j;

64  
65 
s = 0;

66 
for (i = 0; i < 16; i++) { 
67 
for (j = 0; j < 16; j += 8) { 
68 
s += ABS(pix[0]mean);

69 
s += ABS(pix[1]mean);

70 
s += ABS(pix[2]mean);

71 
s += ABS(pix[3]mean);

72 
s += ABS(pix[4]mean);

73 
s += ABS(pix[5]mean);

74 
s += ABS(pix[6]mean);

75 
s += ABS(pix[7]mean);

76 
pix += 8;

77 
} 
78 
pix += line_size  16;

79 
} 
80 
return s;

81 
} 
82  
83 
static int pix_norm1(UINT8 * pix, int line_size) 
84 
{ 
85 
int s, i, j;

86 
UINT32 *sq = squareTbl + 256;

87  
88 
s = 0;

89 
for (i = 0; i < 16; i++) { 
90 
for (j = 0; j < 16; j += 8) { 
91 
s += sq[pix[0]];

92 
s += sq[pix[1]];

93 
s += sq[pix[2]];

94 
s += sq[pix[3]];

95 
s += sq[pix[4]];

96 
s += sq[pix[5]];

97 
s += sq[pix[6]];

98 
s += sq[pix[7]];

99 
pix += 8;

100 
} 
101 
pix += line_size  16;

102 
} 
103 
return s;

104 
} 
105  
106 
static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size) 
107 
{ 
108 
int s, i, j;

109 
UINT32 *sq = squareTbl + 256;

110  
111 
s = 0;

112 
for (i = 0; i < 16; i++) { 
113 
for (j = 0; j < 16; j += 8) { 
114 
s += sq[pix1[0]  pix2[0]]; 
115 
s += sq[pix1[1]  pix2[1]]; 
116 
s += sq[pix1[2]  pix2[2]]; 
117 
s += sq[pix1[3]  pix2[3]]; 
118 
s += sq[pix1[4]  pix2[4]]; 
119 
s += sq[pix1[5]  pix2[5]]; 
120 
s += sq[pix1[6]  pix2[6]]; 
121 
s += sq[pix1[7]  pix2[7]]; 
122 
pix1 += 8;

123 
pix2 += 8;

124 
} 
125 
pix1 += line_size  16;

126 
pix2 += line_size  16;

127 
} 
128 
return s;

129 
} 
130  
131 
static void no_motion_search(MpegEncContext * s, 
132 
int *mx_ptr, int *my_ptr) 
133 
{ 
134 
*mx_ptr = 16 * s>mb_x;

135 
*my_ptr = 16 * s>mb_y;

136 
} 
137  
138 
static int full_motion_search(MpegEncContext * s, 
139 
int *mx_ptr, int *my_ptr, int range, 
140 
int xmin, int ymin, int xmax, int ymax) 
141 
{ 
142 
int x1, y1, x2, y2, xx, yy, x, y;

143 
int mx, my, dmin, d;

144 
UINT8 *pix; 
145  
146 
xx = 16 * s>mb_x;

147 
yy = 16 * s>mb_y;

148 
x1 = xx  range + 1; /* we loose one pixel to avoid boundary pb with half pixel pred */ 
149 
if (x1 < xmin)

150 
x1 = xmin; 
151 
x2 = xx + range  1;

152 
if (x2 > xmax)

153 
x2 = xmax; 
154 
y1 = yy  range + 1;

155 
if (y1 < ymin)

156 
y1 = ymin; 
157 
y2 = yy + range  1;

158 
if (y2 > ymax)

159 
y2 = ymax; 
160 
pix = s>new_picture[0] + (yy * s>linesize) + xx;

161 
dmin = 0x7fffffff;

162 
mx = 0;

163 
my = 0;

164 
for (y = y1; y <= y2; y++) {

165 
for (x = x1; x <= x2; x++) {

166 
d = pix_abs16x16(pix, s>last_picture[0] + (y * s>linesize) + x,

167 
s>linesize, 16);

168 
if (d < dmin 

169 
(d == dmin && 
170 
(abs(x  xx) + abs(y  yy)) < 
171 
(abs(mx  xx) + abs(my  yy)))) { 
172 
dmin = d; 
173 
mx = x; 
174 
my = y; 
175 
} 
176 
} 
177 
} 
178  
179 
*mx_ptr = mx; 
180 
*my_ptr = my; 
181  
182 
#if 0

183 
if (*mx_ptr < (2 * range)  *mx_ptr >= (2 * range) 

184 
*my_ptr < (2 * range)  *my_ptr >= (2 * range)) {

185 
fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);

186 
}

187 
#endif

188 
return dmin;

189 
} 
190  
191  
192 
static int log_motion_search(MpegEncContext * s, 
193 
int *mx_ptr, int *my_ptr, int range, 
194 
int xmin, int ymin, int xmax, int ymax) 
195 
{ 
196 
int x1, y1, x2, y2, xx, yy, x, y;

197 
int mx, my, dmin, d;

198 
UINT8 *pix; 
199  
200 
xx = s>mb_x << 4;

201 
yy = s>mb_y << 4;

202  
203 
/* Left limit */

204 
x1 = xx  range; 
205 
if (x1 < xmin)

206 
x1 = xmin; 
207  
208 
/* Right limit */

209 
x2 = xx + range; 
210 
if (x2 > xmax)

211 
x2 = xmax; 
212  
213 
/* Upper limit */

214 
y1 = yy  range; 
215 
if (y1 < ymin)

216 
y1 = ymin; 
217  
218 
/* Lower limit */

219 
y2 = yy + range; 
220 
if (y2 > ymax)

221 
y2 = ymax; 
222  
223 
pix = s>new_picture[0] + (yy * s>linesize) + xx;

224 
dmin = 0x7fffffff;

225 
mx = 0;

226 
my = 0;

227  
228 
do {

229 
for (y = y1; y <= y2; y += range) {

230 
for (x = x1; x <= x2; x += range) {

231 
d = pix_abs16x16(pix, s>last_picture[0] + (y * s>linesize) + x, s>linesize, 16); 
232 
if (d < dmin  (d == dmin && (abs(x  xx) + abs(y  yy)) < (abs(mx  xx) + abs(my  yy)))) {

233 
dmin = d; 
234 
mx = x; 
235 
my = y; 
236 
} 
237 
} 
238 
} 
239  
240 
range = range >> 1;

241  
242 
x1 = mx  range; 
243 
if (x1 < xmin)

244 
x1 = xmin; 
245  
246 
x2 = mx + range; 
247 
if (x2 > xmax)

248 
x2 = xmax; 
249  
250 
y1 = my  range; 
251 
if (y1 < ymin)

252 
y1 = ymin; 
253  
254 
y2 = my + range; 
255 
if (y2 > ymax)

256 
y2 = ymax; 
257  
258 
} while (range >= 1); 
259  
260 
#ifdef DEBUG

261 
fprintf(stderr, "log  MX: %d\tMY: %d\n", mx, my);

262 
#endif

263 
*mx_ptr = mx; 
264 
*my_ptr = my; 
265 
return dmin;

266 
} 
267  
268 
static int phods_motion_search(MpegEncContext * s, 
269 
int *mx_ptr, int *my_ptr, int range, 
270 
int xmin, int ymin, int xmax, int ymax) 
271 
{ 
272 
int x1, y1, x2, y2, xx, yy, x, y, lastx, d;

273 
int mx, my, dminx, dminy;

274 
UINT8 *pix; 
275  
276 
xx = s>mb_x << 4;

277 
yy = s>mb_y << 4;

278  
279 
/* Left limit */

280 
x1 = xx  range; 
281 
if (x1 < xmin)

282 
x1 = xmin; 
283  
284 
/* Right limit */

285 
x2 = xx + range; 
286 
if (x2 > xmax)

287 
x2 = xmax; 
288  
289 
/* Upper limit */

290 
y1 = yy  range; 
291 
if (y1 < ymin)

292 
y1 = ymin; 
293  
294 
/* Lower limit */

295 
y2 = yy + range; 
296 
if (y2 > ymax)

297 
y2 = ymax; 
298  
299 
pix = s>new_picture[0] + (yy * s>linesize) + xx;

300 
mx = 0;

301 
my = 0;

302  
303 
x = xx; 
304 
y = yy; 
305 
do {

306 
dminx = 0x7fffffff;

307 
dminy = 0x7fffffff;

308  
309 
lastx = x; 
310 
for (x = x1; x <= x2; x += range) {

311 
d = pix_abs16x16(pix, s>last_picture[0] + (y * s>linesize) + x, s>linesize, 16); 
312 
if (d < dminx  (d == dminx && (abs(x  xx) + abs(y  yy)) < (abs(mx  xx) + abs(my  yy)))) {

313 
dminx = d; 
314 
mx = x; 
315 
} 
316 
} 
317  
318 
x = lastx; 
319 
for (y = y1; y <= y2; y += range) {

320 
d = pix_abs16x16(pix, s>last_picture[0] + (y * s>linesize) + x, s>linesize, 16); 
321 
if (d < dminy  (d == dminy && (abs(x  xx) + abs(y  yy)) < (abs(mx  xx) + abs(my  yy)))) {

322 
dminy = d; 
323 
my = y; 
324 
} 
325 
} 
326  
327 
range = range >> 1;

328  
329 
x = mx; 
330 
y = my; 
331 
x1 = mx  range; 
332 
if (x1 < xmin)

333 
x1 = xmin; 
334  
335 
x2 = mx + range; 
336 
if (x2 > xmax)

337 
x2 = xmax; 
338  
339 
y1 = my  range; 
340 
if (y1 < ymin)

341 
y1 = ymin; 
342  
343 
y2 = my + range; 
344 
if (y2 > ymax)

345 
y2 = ymax; 
346  
347 
} while (range >= 1); 
348  
349 
#ifdef DEBUG

350 
fprintf(stderr, "phods  MX: %d\tMY: %d\n", mx, my);

351 
#endif

352  
353 
/* half pixel search */

354 
*mx_ptr = mx; 
355 
*my_ptr = my; 
356 
return dminy;

357 
} 
358  
359  
360 
#define Z_THRESHOLD 256 
361  
362 
#define CHECK_MV(x,y)\

363 
{\ 
364 
d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\

365 
d += (mv_penalty[((x)<<shift)pred_x] + mv_penalty[((y)<<shift)pred_y])*quant;\ 
366 
if(d<dmin){\

367 
best[0]=x;\

368 
best[1]=y;\

369 
dmin=d;\ 
370 
}\ 
371 
} 
372  
373 
#define CHECK_MV_DIR(x,y,new_dir)\

374 
{\ 
375 
d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\

376 
d += (mv_penalty[((x)<<shift)pred_x] + mv_penalty[((y)<<shift)pred_y])*quant;\ 
377 
if(d<dmin){\

378 
best[0]=x;\

379 
best[1]=y;\

380 
dmin=d;\ 
381 
next_dir= new_dir;\ 
382 
}\ 
383 
} 
384  
385 
#define check(x,y,S,v)\

386 
if( (x)<(xmin<<(S)) ) printf("%d %d %d %d xmin" #v, (x), (y), s>mb_x, s>mb_y);\ 
387 
if( (x)>(xmax<<(S)) ) printf("%d %d %d %d xmax" #v, (x), (y), s>mb_x, s>mb_y);\ 
388 
if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s>mb_x, s>mb_y);\ 
389 
if( (y)>(ymax<<(S)) ) printf("%d %d %d %d ymax" #v, (x), (y), s>mb_x, s>mb_y);\ 
390  
391  
392 
static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, 
393 
UINT8 *new_pic, UINT8 *old_pic, int pic_stride,

394 
int pred_x, int pred_y, UINT16 *mv_penalty, int quant, 
395 
int xmin, int ymin, int xmax, int ymax, int shift) 
396 
{ 
397 
int next_dir=1; 
398  
399 
for(;;){

400 
int d;

401 
const int dir= next_dir; 
402 
const int x= best[0]; 
403 
const int y= best[1]; 
404 
next_dir=1;

405  
406 
//printf("%d", dir);

407 
if(dir!=2 && x>xmin) CHECK_MV_DIR(x1, y , 0) 
408 
if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y1, 1) 
409 
if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2) 
410 
if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3) 
411  
412 
if(next_dir==1){ 
413 
return dmin;

414 
} 
415 
} 
416  
417 
/* for(;;){

418 
int d;

419 
const int x= best[0];

420 
const int y= best[1];

421 
const int last_min=dmin;

422 
if(x>xmin) CHECK_MV(x1, y )

423 
if(y>xmin) CHECK_MV(x , y1)

424 
if(x<xmax) CHECK_MV(x+1, y )

425 
if(y<xmax) CHECK_MV(x , y+1)

426 
if(x>xmin && y>ymin) CHECK_MV(x1, y1)

427 
if(x>xmin && y<ymax) CHECK_MV(x1, y+1)

428 
if(x<xmax && y>ymin) CHECK_MV(x+1, y1)

429 
if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)

430 
if(x1>xmin) CHECK_MV(x2, y )

431 
if(y1>xmin) CHECK_MV(x , y2)

432 
if(x+1<xmax) CHECK_MV(x+2, y )

433 
if(y+1<xmax) CHECK_MV(x , y+2)

434 
if(x1>xmin && y1>ymin) CHECK_MV(x2, y2)

435 
if(x1>xmin && y+1<ymax) CHECK_MV(x2, y+2)

436 
if(x+1<xmax && y1>ymin) CHECK_MV(x+2, y2)

437 
if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)

438 
if(dmin==last_min) return dmin;

439 
}

440 
*/

441 
} 
442  
443 
static inline int snake_search(MpegEncContext * s, int *best, int dmin, 
444 
UINT8 *new_pic, UINT8 *old_pic, int pic_stride,

445 
int pred_x, int pred_y, UINT16 *mv_penalty, int quant, 
446 
int xmin, int ymin, int xmax, int ymax, int shift) 
447 
{ 
448 
int dir=0; 
449 
int c=1; 
450 
static int x_dir[8]= {1,1,0,1,1,1, 0, 1}; 
451 
static int y_dir[8]= {0,1,1, 1, 0,1,1,1}; 
452 
int fails=0; 
453 
int last_d[2]={dmin, dmin}; 
454  
455 
/*static int good=0;

456 
static int bad=0;

457 
static int point=0;

458 

459 
point++;

460 
if(256*256*256*64%point==0)

461 
{

462 
printf("%d %d %d\n", good, bad, point);

463 
}*/

464  
465 
for(;;){

466 
int x= best[0]; 
467 
int y= best[1]; 
468 
int d;

469 
x+=x_dir[dir]; 
470 
y+=y_dir[dir]; 
471 
if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){

472 
d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);

473 
d += (mv_penalty[((x)<<shift)pred_x] + mv_penalty[((y)<<shift)pred_y])*quant; 
474 
}else{

475 
d = dmin + 10000; //FIXME smarter boundary handling 
476 
} 
477 
if(d<dmin){

478 
best[0]=x;

479 
best[1]=y;

480 
dmin=d; 
481  
482 
if(last_d[1]  last_d[0] > last_d[0]  d) c= c; 
483 
dir+=c; 
484  
485 
fails=0;

486 
//good++;

487 
last_d[1]=last_d[0]; 
488 
last_d[0]=d;

489 
}else{

490 
//bad++;

491 
if(fails){

492 
if(fails>=3) return dmin; 
493 
}else{

494 
c= c; 
495 
} 
496 
dir+=c*2;

497 
fails++; 
498 
} 
499 
dir&=7;

500 
} 
501 
} 
502  
503 
static int epzs_motion_search(MpegEncContext * s, 
504 
int *mx_ptr, int *my_ptr, 
505 
int P[5][2], int pred_x, int pred_y, 
506 
int xmin, int ymin, int xmax, int ymax) 
507 
{ 
508 
int best[2]={0, 0}; 
509 
int d, dmin;

510 
UINT8 *new_pic, *old_pic; 
511 
const int pic_stride= s>linesize; 
512 
const int pic_xy= (s>mb_y*pic_stride + s>mb_x)*16; 
513 
UINT16 *mv_penalty= s>mv_penalty[s>f_code] + MAX_MV; // f_code of the prev frame

514 
int quant= s>qscale; // qscale of the prev frame 
515 
const int shift= 1+s>quarter_sample; 
516  
517 
new_pic = s>new_picture[0] + pic_xy;

518 
old_pic = s>last_picture[0] + pic_xy;

519 

520 
dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);

521 
if(dmin<Z_THRESHOLD){

522 
*mx_ptr= 0;

523 
*my_ptr= 0;

524 
//printf("Z");

525 
return dmin;

526 
} 
527  
528 
/* first line */

529 
if ((s>mb_y == 0  s>first_slice_line  s>first_gob_line)) { 
530 
CHECK_MV(P[1][0]>>shift, P[1][1]>>shift) 
531 
}else{

532 
CHECK_MV(P[4][0]>>shift, P[4][1]>>shift) 
533 
if(dmin<Z_THRESHOLD){

534 
*mx_ptr= P[4][0]>>shift; 
535 
*my_ptr= P[4][1]>>shift; 
536 
//printf("M\n");

537 
return dmin;

538 
} 
539 
CHECK_MV(P[1][0]>>shift, P[1][1]>>shift) 
540 
CHECK_MV(P[2][0]>>shift, P[2][1]>>shift) 
541 
CHECK_MV(P[3][0]>>shift, P[3][1]>>shift) 
542 
} 
543 
CHECK_MV(P[0][0]>>shift, P[0][1]>>shift) 
544  
545 
//check(best[0],best[1],0, b0)

546 
if(s>full_search==ME_EPZS)

547 
dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 
548 
pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); 
549 
else

550 
dmin= snake_search(s, best, dmin, new_pic, old_pic, pic_stride, 
551 
pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); 
552 
//check(best[0],best[1],0, b1)

553 
*mx_ptr= best[0];

554 
*my_ptr= best[1];

555  
556 
// printf("%d %d %d \n", best[0], best[1], dmin);

557 
return dmin;

558 
} 
559  
560 
#define CHECK_HALF_MV(suffix, x, y) \

561 
d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s>linesize, 16);\ 
562 
d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\ 
563 
if(d<dminh){\

564 
dminh= d;\ 
565 
mx= mx1 + x;\ 
566 
my= my1 + y;\ 
567 
} 
568  
569 
/* The idea would be to make half pel ME after Inter/Intra decision to

570 
save time. */

571 
static inline void halfpel_motion_search(MpegEncContext * s, 
572 
int *mx_ptr, int *my_ptr, int dmin, 
573 
int xmin, int ymin, int xmax, int ymax, 
574 
int pred_x, int pred_y) 
575 
{ 
576 
UINT16 *mv_penalty= s>mv_penalty[s>f_code] + MAX_MV; // f_code of the prev frame

577 
const int quant= s>qscale; 
578 
int pen_x, pen_y;

579 
int mx, my, mx1, my1, d, xx, yy, dminh;

580 
UINT8 *pix, *ptr; 
581  
582 
mx = *mx_ptr; 
583 
my = *my_ptr; 
584 
ptr = s>last_picture[0] + (my * s>linesize) + mx;

585  
586 
xx = 16 * s>mb_x;

587 
yy = 16 * s>mb_y;

588 
pix = s>new_picture[0] + (yy * s>linesize) + xx;

589 

590 
dminh = dmin; 
591  
592 
if (mx > xmin && mx < xmax &&

593 
my > ymin && my < ymax) { 
594  
595 
mx= mx1= 2*(mx  xx);

596 
my= my1= 2*(my  yy);

597 
if(dmin < Z_THRESHOLD && mx==0 && my==0){ 
598 
*mx_ptr = 0;

599 
*my_ptr = 0;

600 
return;

601 
} 
602 

603 
pen_x= pred_x + mx; 
604 
pen_y= pred_y + my; 
605  
606 
ptr= s>linesize; 
607 
CHECK_HALF_MV(xy2, 1, 1) 
608 
CHECK_HALF_MV(y2 , 0, 1) 
609 
CHECK_HALF_MV(xy2, +1, 1) 
610 

611 
ptr+= s>linesize; 
612 
CHECK_HALF_MV(x2 , 1, 0) 
613 
CHECK_HALF_MV(x2 , +1, 0) 
614 
CHECK_HALF_MV(xy2, 1, +1) 
615 
CHECK_HALF_MV(y2 , 0, +1) 
616 
CHECK_HALF_MV(xy2, +1, +1) 
617 
}else{

618 
mx= 2*(mx  xx);

619 
my= 2*(my  yy);

620 
} 
621  
622 
*mx_ptr = mx; 
623 
*my_ptr = my; 
624 
} 
625  
626 
#ifndef CONFIG_TEST_MV_ENCODE

627  
628 
int estimate_motion(MpegEncContext * s,

629 
int mb_x, int mb_y, 
630 
int *mx_ptr, int *my_ptr) 
631 
{ 
632 
UINT8 *pix, *ppix; 
633 
int sum, varc, vard, mx, my, range, dmin, xx, yy;

634 
int xmin, ymin, xmax, ymax;

635 
int rel_xmin, rel_ymin, rel_xmax, rel_ymax;

636 
int pred_x=0, pred_y=0; 
637 
int P[5][2]; 
638 
const int shift= 1+s>quarter_sample; 
639 

640 
range = 8 * (1 << (s>f_code  1)); 
641 
/* XXX: temporary kludge to avoid overflow for msmpeg4 */

642 
if (s>out_format == FMT_H263 && !s>h263_msmpeg4)

643 
range = range * 2;

644  
645 
if (s>unrestricted_mv) {

646 
xmin = 16;

647 
ymin = 16;

648 
if (s>h263_plus)

649 
range *= 2;

650 
if(s>avctx==NULL  s>avctx>codec>id!=CODEC_ID_MPEG4){ 
651 
xmax = s>mb_width*16;

652 
ymax = s>mb_height*16;

653 
}else {

654 
/* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise

655 
(cuz the drawn edge isnt large enough))*/

656 
xmax = s>width; 
657 
ymax = s>height; 
658 
} 
659 
} else {

660 
xmin = 0;

661 
ymin = 0;

662 
xmax = s>mb_width*16  16; 
663 
ymax = s>mb_height*16  16; 
664 
} 
665 
switch(s>full_search) {

666 
case ME_ZERO:

667 
default:

668 
no_motion_search(s, &mx, &my); 
669 
dmin = 0;

670 
break;

671 
case ME_FULL:

672 
dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax); 
673 
break;

674 
case ME_LOG:

675 
dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);

676 
break;

677 
case ME_PHODS:

678 
dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);

679 
break;

680 
case ME_X1:

681 
case ME_EPZS:

682 
{ 
683 
static const int off[4]= {2, 1, 1, 1}; 
684 
const int mot_stride = s>mb_width*2 + 2; 
685 
const int mot_xy = (s>mb_y*2 + 1)*mot_stride + s>mb_x*2 + 1; 
686  
687 
rel_xmin= xmin  s>mb_x*16;

688 
rel_xmax= xmax  s>mb_x*16;

689 
rel_ymin= ymin  s>mb_y*16;

690 
rel_ymax= ymax  s>mb_y*16;

691  
692 
P[0][0] = s>motion_val[mot_xy ][0]; 
693 
P[0][1] = s>motion_val[mot_xy ][1]; 
694 
P[1][0] = s>motion_val[mot_xy  1][0]; 
695 
P[1][1] = s>motion_val[mot_xy  1][1]; 
696 
if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift); 
697  
698 
/* special case for first line */

699 
if ((s>mb_y == 0  s>first_slice_line  s>first_gob_line)) { 
700 
P[4][0] = P[1][0]; 
701 
P[4][1] = P[1][1]; 
702 
} else {

703 
P[2][0] = s>motion_val[mot_xy  mot_stride ][0]; 
704 
P[2][1] = s>motion_val[mot_xy  mot_stride ][1]; 
705 
P[3][0] = s>motion_val[mot_xy  mot_stride + off[0] ][0]; 
706 
P[3][1] = s>motion_val[mot_xy  mot_stride + off[0] ][1]; 
707 
if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift); 
708 
if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift); 
709 
if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift); 
710 

711 
P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); 
712 
P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]); 
713 
} 
714 
if(s>out_format == FMT_H263){

715 
pred_x = P[4][0]; 
716 
pred_y = P[4][1]; 
717 
}else { /* mpeg1 at least */ 
718 
pred_x= P[1][0]; 
719 
pred_y= P[1][1]; 
720 
} 
721 
} 
722 
dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); 
723 

724 
mx+= s>mb_x*16;

725 
my+= s>mb_y*16;

726 
break;

727 
} 
728  
729 
/* intra / predictive decision */

730 
xx = mb_x * 16;

731 
yy = mb_y * 16;

732  
733 
pix = s>new_picture[0] + (yy * s>linesize) + xx;

734 
/* At this point (mx,my) are fullpell and the absolute displacement */

735 
ppix = s>last_picture[0] + (my * s>linesize) + mx;

736  
737 
sum = pix_sum(pix, s>linesize); 
738 
varc = pix_dev(pix, s>linesize, (sum+128)>>8); 
739 
vard = pix_abs16x16(pix, ppix, s>linesize, 16);

740  
741 
s>mb_var[s>mb_width * mb_y + mb_x] = varc; 
742 
s>avg_mb_var += varc; 
743 
s>mc_mb_var += vard; 
744  
745 
#if 0

746 
printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",

747 
varc, s>avg_mb_var, sum, vard, mx  xx, my  yy);

748 
#endif

749 
if (vard <= 64  vard < varc + INTER_BIAS) { 
750 
if (s>full_search != ME_ZERO) {

751 
halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); 
752 
} else {

753 
mx = 16 * s>mb_x;

754 
my = 16 * s>mb_y;

755 
} 
756 
// check(mx + 32*s>mb_x, my + 32*s>mb_y, 1, end)

757  
758 
*mx_ptr = mx; 
759 
*my_ptr = my; 
760 
return 0; 
761 
} else {

762 
*mx_ptr = 0;

763 
*my_ptr = 0;

764 
return 1; 
765 
} 
766 
} 
767  
768 
#else

769  
770 
/* test version which generates valid random vectors */

771 
int estimate_motion(MpegEncContext * s,

772 
int mb_x, int mb_y, 
773 
int *mx_ptr, int *my_ptr) 
774 
{ 
775 
int xx, yy, x1, y1, x2, y2, range;

776  
777 
if ((random() % 10) >= 5) { 
778 
range = 8 * (1 << (s>f_code  1)); 
779 
if (s>out_format == FMT_H263 && !s>h263_msmpeg4)

780 
range = range * 2;

781  
782 
xx = 16 * s>mb_x;

783 
yy = 16 * s>mb_y;

784 
x1 = xx  range; 
785 
if (x1 < 0) 
786 
x1 = 0;

787 
x2 = xx + range  1;

788 
if (x2 > (s>width  16)) 
789 
x2 = s>width  16;

790 
y1 = yy  range; 
791 
if (y1 < 0) 
792 
y1 = 0;

793 
y2 = yy + range  1;

794 
if (y2 > (s>height  16)) 
795 
y2 = s>height  16;

796  
797 
*mx_ptr = (random() % (2 * (x2  x1 + 1))) + 2 * (x1  xx); 
798 
*my_ptr = (random() % (2 * (y2  y1 + 1))) + 2 * (y1  yy); 
799 
return 0; 
800 
} else {

801 
*mx_ptr = 0;

802 
*my_ptr = 0;

803 
return 1; 
804 
} 
805 
} 
806  
807 
#endif
