ffmpeg / libavcodec / motion_est.c @ 11ce8834
History  View  Annotate  Download (21.5 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 
static void halfpel_motion_search(MpegEncContext * s, 
29 
int *mx_ptr, int *my_ptr, int dmin, 
30 
int xmin, int ymin, int xmax, int ymax, 
31 
int pred_x, int pred_y); 
32  
33 
/* config it to test motion vector encoding (send random vectors) */

34 
//#define CONFIG_TEST_MV_ENCODE

35  
36 
static int pix_sum(UINT8 * pix, int line_size) 
37 
{ 
38 
int s, i, j;

39  
40 
s = 0;

41 
for (i = 0; i < 16; i++) { 
42 
for (j = 0; j < 16; j += 8) { 
43 
s += pix[0];

44 
s += pix[1];

45 
s += pix[2];

46 
s += pix[3];

47 
s += pix[4];

48 
s += pix[5];

49 
s += pix[6];

50 
s += pix[7];

51 
pix += 8;

52 
} 
53 
pix += line_size  16;

54 
} 
55 
return s;

56 
} 
57  
58 
static int pix_norm1(UINT8 * pix, int line_size) 
59 
{ 
60 
int s, i, j;

61 
UINT32 *sq = squareTbl + 256;

62  
63 
s = 0;

64 
for (i = 0; i < 16; i++) { 
65 
for (j = 0; j < 16; j += 8) { 
66 
s += sq[pix[0]];

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

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

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

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

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

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

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

74 
pix += 8;

75 
} 
76 
pix += line_size  16;

77 
} 
78 
return s;

79 
} 
80  
81 
static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size) 
82 
{ 
83 
int s, i, j;

84 
UINT32 *sq = squareTbl + 256;

85  
86 
s = 0;

87 
for (i = 0; i < 16; i++) { 
88 
for (j = 0; j < 16; j += 8) { 
89 
s += sq[pix1[0]  pix2[0]]; 
90 
s += sq[pix1[1]  pix2[1]]; 
91 
s += sq[pix1[2]  pix2[2]]; 
92 
s += sq[pix1[3]  pix2[3]]; 
93 
s += sq[pix1[4]  pix2[4]]; 
94 
s += sq[pix1[5]  pix2[5]]; 
95 
s += sq[pix1[6]  pix2[6]]; 
96 
s += sq[pix1[7]  pix2[7]]; 
97 
pix1 += 8;

98 
pix2 += 8;

99 
} 
100 
pix1 += line_size  16;

101 
pix2 += line_size  16;

102 
} 
103 
return s;

104 
} 
105  
106 
static void no_motion_search(MpegEncContext * s, 
107 
int *mx_ptr, int *my_ptr) 
108 
{ 
109 
*mx_ptr = 16 * s>mb_x;

110 
*my_ptr = 16 * s>mb_y;

111 
} 
112  
113 
static int full_motion_search(MpegEncContext * s, 
114 
int *mx_ptr, int *my_ptr, int range, 
115 
int xmin, int ymin, int xmax, int ymax) 
116 
{ 
117 
int x1, y1, x2, y2, xx, yy, x, y;

118 
int mx, my, dmin, d;

119 
UINT8 *pix; 
120  
121 
xx = 16 * s>mb_x;

122 
yy = 16 * s>mb_y;

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

125 
x1 = xmin; 
126 
x2 = xx + range  1;

127 
if (x2 > xmax)

128 
x2 = xmax; 
129 
y1 = yy  range + 1;

130 
if (y1 < ymin)

131 
y1 = ymin; 
132 
y2 = yy + range  1;

133 
if (y2 > ymax)

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

136 
dmin = 0x7fffffff;

137 
mx = 0;

138 
my = 0;

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

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

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

142 
s>linesize, 16);

143 
if (d < dmin 

144 
(d == dmin && 
145 
(abs(x  xx) + abs(y  yy)) < 
146 
(abs(mx  xx) + abs(my  yy)))) { 
147 
dmin = d; 
148 
mx = x; 
149 
my = y; 
150 
} 
151 
} 
152 
} 
153  
154 
*mx_ptr = mx; 
155 
*my_ptr = my; 
156  
157 
#if 0

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

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

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

161 
}

162 
#endif

163 
return dmin;

164 
} 
165  
166  
167 
static int log_motion_search(MpegEncContext * s, 
168 
int *mx_ptr, int *my_ptr, int range, 
169 
int xmin, int ymin, int xmax, int ymax) 
170 
{ 
171 
int x1, y1, x2, y2, xx, yy, x, y;

172 
int mx, my, dmin, d;

173 
UINT8 *pix; 
174  
175 
xx = s>mb_x << 4;

176 
yy = s>mb_y << 4;

177  
178 
/* Left limit */

179 
x1 = xx  range; 
180 
if (x1 < xmin)

181 
x1 = xmin; 
182  
183 
/* Right limit */

184 
x2 = xx + range; 
185 
if (x2 > xmax)

186 
x2 = xmax; 
187  
188 
/* Upper limit */

189 
y1 = yy  range; 
190 
if (y1 < ymin)

191 
y1 = ymin; 
192  
193 
/* Lower limit */

194 
y2 = yy + range; 
195 
if (y2 > ymax)

196 
y2 = ymax; 
197  
198 
pix = s>new_picture[0] + (yy * s>linesize) + xx;

199 
dmin = 0x7fffffff;

200 
mx = 0;

201 
my = 0;

202  
203 
do {

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

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

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

208 
dmin = d; 
209 
mx = x; 
210 
my = y; 
211 
} 
212 
} 
213 
} 
214  
215 
range = range >> 1;

216  
217 
x1 = mx  range; 
218 
if (x1 < xmin)

219 
x1 = xmin; 
220  
221 
x2 = mx + range; 
222 
if (x2 > xmax)

223 
x2 = xmax; 
224  
225 
y1 = my  range; 
226 
if (y1 < ymin)

227 
y1 = ymin; 
228  
229 
y2 = my + range; 
230 
if (y2 > ymax)

231 
y2 = ymax; 
232  
233 
} while (range >= 1); 
234  
235 
#ifdef DEBUG

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

237 
#endif

238 
*mx_ptr = mx; 
239 
*my_ptr = my; 
240 
return dmin;

241 
} 
242  
243 
static int phods_motion_search(MpegEncContext * s, 
244 
int *mx_ptr, int *my_ptr, int range, 
245 
int xmin, int ymin, int xmax, int ymax) 
246 
{ 
247 
int x1, y1, x2, y2, xx, yy, x, y, lastx, d;

248 
int mx, my, dminx, dminy;

249 
UINT8 *pix; 
250  
251 
xx = s>mb_x << 4;

252 
yy = s>mb_y << 4;

253  
254 
/* Left limit */

255 
x1 = xx  range; 
256 
if (x1 < xmin)

257 
x1 = xmin; 
258  
259 
/* Right limit */

260 
x2 = xx + range; 
261 
if (x2 > xmax)

262 
x2 = xmax; 
263  
264 
/* Upper limit */

265 
y1 = yy  range; 
266 
if (y1 < ymin)

267 
y1 = ymin; 
268  
269 
/* Lower limit */

270 
y2 = yy + range; 
271 
if (y2 > ymax)

272 
y2 = ymax; 
273  
274 
pix = s>new_picture[0] + (yy * s>linesize) + xx;

275 
mx = 0;

276 
my = 0;

277  
278 
x = xx; 
279 
y = yy; 
280 
do {

281 
dminx = 0x7fffffff;

282 
dminy = 0x7fffffff;

283  
284 
lastx = x; 
285 
for (x = x1; x <= x2; x += range) {

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

288 
dminx = d; 
289 
mx = x; 
290 
} 
291 
} 
292  
293 
x = lastx; 
294 
for (y = y1; y <= y2; y += range) {

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

297 
dminy = d; 
298 
my = y; 
299 
} 
300 
} 
301  
302 
range = range >> 1;

303  
304 
x = mx; 
305 
y = my; 
306 
x1 = mx  range; 
307 
if (x1 < xmin)

308 
x1 = xmin; 
309  
310 
x2 = mx + range; 
311 
if (x2 > xmax)

312 
x2 = xmax; 
313  
314 
y1 = my  range; 
315 
if (y1 < ymin)

316 
y1 = ymin; 
317  
318 
y2 = my + range; 
319 
if (y2 > ymax)

320 
y2 = ymax; 
321  
322 
} while (range >= 1); 
323  
324 
#ifdef DEBUG

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

326 
#endif

327  
328 
/* half pixel search */

329 
*mx_ptr = mx; 
330 
*my_ptr = my; 
331 
return dminy;

332 
} 
333  
334  
335 
#define Z_THRESHOLD 256 
336  
337 
#define CHECK_MV(x,y)\

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

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

342 
best[0]=x;\

343 
best[1]=y;\

344 
dmin=d;\ 
345 
}\ 
346 
} 
347  
348 
#define CHECK_MV_DIR(x,y,new_dir)\

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

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

353 
best[0]=x;\

354 
best[1]=y;\

355 
dmin=d;\ 
356 
next_dir= new_dir;\ 
357 
}\ 
358 
} 
359  
360 
#define check(x,y,S,v)\

361 
if( (x)<(xmin<<(S)) ) printf("%d %d %d %d xmin" #v, (x), (y), s>mb_x, s>mb_y);\ 
362 
if( (x)>(xmax<<(S)) ) printf("%d %d %d %d xmax" #v, (x), (y), s>mb_x, s>mb_y);\ 
363 
if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s>mb_x, s>mb_y);\ 
364 
if( (y)>(ymax<<(S)) ) printf("%d %d %d %d ymax" #v, (x), (y), s>mb_x, s>mb_y);\ 
365  
366  
367 
static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, 
368 
UINT8 *new_pic, UINT8 *old_pic, int pic_stride,

369 
int pred_x, int pred_y, UINT16 *mv_penalty, int quant, 
370 
int xmin, int ymin, int xmax, int ymax, int shift) 
371 
{ 
372 
int next_dir=1; 
373  
374 
for(;;){

375 
int d;

376 
const int dir= next_dir; 
377 
const int x= best[0]; 
378 
const int y= best[1]; 
379 
next_dir=1;

380  
381 
//printf("%d", dir);

382 
if(dir!=2 && x>xmin) CHECK_MV_DIR(x1, y , 0) 
383 
if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y1, 1) 
384 
if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2) 
385 
if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3) 
386  
387 
if(next_dir==1){ 
388 
return dmin;

389 
} 
390 
} 
391  
392 
/* for(;;){

393 
int d;

394 
const int x= best[0];

395 
const int y= best[1];

396 
const int last_min=dmin;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

413 
if(dmin==last_min) return dmin;

414 
}

415 
*/

416 
} 
417  
418 
static inline int snake_search(MpegEncContext * s, int *best, int dmin, 
419 
UINT8 *new_pic, UINT8 *old_pic, int pic_stride,

420 
int pred_x, int pred_y, UINT16 *mv_penalty, int quant, 
421 
int xmin, int ymin, int xmax, int ymax, int shift) 
422 
{ 
423 
int dir=0; 
424 
int c=1; 
425 
static int x_dir[8]= {1,1,0,1,1,1, 0, 1}; 
426 
static int y_dir[8]= {0,1,1, 1, 0,1,1,1}; 
427 
int fails=0; 
428 
int last_d[2]={dmin, dmin}; 
429  
430 
/*static int good=0;

431 
static int bad=0;

432 
static int point=0;

433 

434 
point++;

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

436 
{

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

438 
}*/

439  
440 
for(;;){

441 
int x= best[0]; 
442 
int y= best[1]; 
443 
int d;

444 
x+=x_dir[dir]; 
445 
y+=y_dir[dir]; 
446 
if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){

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

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

450 
d = dmin + 10000; //FIXME smarter boundary handling 
451 
} 
452 
if(d<dmin){

453 
best[0]=x;

454 
best[1]=y;

455 
dmin=d; 
456  
457 
if(last_d[1]  last_d[0] > last_d[0]  d) c= c; 
458 
dir+=c; 
459  
460 
fails=0;

461 
//good++;

462 
last_d[1]=last_d[0]; 
463 
last_d[0]=d;

464 
}else{

465 
//bad++;

466 
if(fails){

467 
if(fails>=3) return dmin; 
468 
}else{

469 
c= c; 
470 
} 
471 
dir+=c*2;

472 
fails++; 
473 
} 
474 
dir&=7;

475 
} 
476 
} 
477  
478 
static int epzs_motion_search(MpegEncContext * s, 
479 
int *mx_ptr, int *my_ptr, 
480 
int P[5][2], int pred_x, int pred_y, 
481 
int xmin, int ymin, int xmax, int ymax) 
482 
{ 
483 
int best[2]={0, 0}; 
484 
int d, dmin;

485 
UINT8 *new_pic, *old_pic; 
486 
const int pic_stride= s>linesize; 
487 
const int pic_xy= (s>mb_y*pic_stride + s>mb_x)*16; 
488 
UINT16 *mv_penalty= s>mv_penalty[s>f_code] + MAX_MV; // f_code of the prev frame

489 
int quant= s>qscale; // qscale of the prev frame 
490 
const int shift= 1+s>quarter_sample; 
491  
492 
new_pic = s>new_picture[0] + pic_xy;

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

494 

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

496 
if(dmin<Z_THRESHOLD){

497 
*mx_ptr= 0;

498 
*my_ptr= 0;

499 
//printf("Z");

500 
return dmin;

501 
} 
502  
503 
/* first line */

504 
if ((s>mb_y == 0  s>first_slice_line  s>first_gob_line)) { 
505 
CHECK_MV(P[1][0]>>shift, P[1][1]>>shift) 
506 
}else{

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

509 
*mx_ptr= P[4][0]>>shift; 
510 
*my_ptr= P[4][1]>>shift; 
511 
//printf("M\n");

512 
return dmin;

513 
} 
514 
CHECK_MV(P[1][0]>>shift, P[1][1]>>shift) 
515 
CHECK_MV(P[2][0]>>shift, P[2][1]>>shift) 
516 
CHECK_MV(P[3][0]>>shift, P[3][1]>>shift) 
517 
} 
518 
CHECK_MV(P[0][0]>>shift, P[0][1]>>shift) 
519  
520 
//check(best[0],best[1],0, b0)

521 
if(s>full_search==ME_EPZS)

522 
dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 
523 
pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); 
524 
else

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

528 
*mx_ptr= best[0];

529 
*my_ptr= best[1];

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

532 
return dmin;

533 
} 
534  
535 
#define CHECK_HALF_MV(suffix, x, y) \

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

539 
dminh= d;\ 
540 
mx= mx1 + x;\ 
541 
my= my1 + y;\ 
542 
} 
543  
544 
/* The idea would be to make half pel ME after Inter/Intra decision to

545 
save time. */

546 
static inline void halfpel_motion_search(MpegEncContext * s, 
547 
int *mx_ptr, int *my_ptr, int dmin, 
548 
int xmin, int ymin, int xmax, int ymax, 
549 
int pred_x, int pred_y) 
550 
{ 
551 
UINT16 *mv_penalty= s>mv_penalty[s>f_code] + MAX_MV; // f_code of the prev frame

552 
const int quant= s>qscale; 
553 
int pen_x, pen_y;

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

555 
UINT8 *pix, *ptr; 
556  
557 

558 
mx = *mx_ptr; 
559 
my = *my_ptr; 
560 
ptr = s>last_picture[0] + (my * s>linesize) + mx;

561  
562 
xx = 16 * s>mb_x;

563 
yy = 16 * s>mb_y;

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

565 

566 
dminh = dmin; 
567  
568 
if (mx > xmin && mx < xmax &&

569 
my > ymin && my < ymax) { 
570  
571 
mx= mx1= 2*(mx  xx);

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

573 
if(dmin < Z_THRESHOLD && mx==0 && my==0){ 
574 
*mx_ptr = 0;

575 
*my_ptr = 0;

576 
return;

577 
} 
578 

579 
pen_x= pred_x + mx; 
580 
pen_y= pred_y + my; 
581  
582 
ptr= s>linesize; 
583 
CHECK_HALF_MV(xy2, 1, 1) 
584 
CHECK_HALF_MV(y2 , 0, 1) 
585 
CHECK_HALF_MV(xy2, +1, 1) 
586 

587 
ptr+= s>linesize; 
588 
CHECK_HALF_MV(x2 , 1, 0) 
589 
CHECK_HALF_MV(x2 , +1, 0) 
590 
CHECK_HALF_MV(xy2, 1, +1) 
591 
CHECK_HALF_MV(y2 , 0, +1) 
592 
CHECK_HALF_MV(xy2, +1, +1) 
593 
}else{

594 
mx= 2*(mx  xx);

595 
my= 2*(my  yy);

596 
} 
597  
598 
*mx_ptr = mx; 
599 
*my_ptr = my; 
600 
} 
601  
602 
#ifndef CONFIG_TEST_MV_ENCODE

603  
604 
int estimate_motion(MpegEncContext * s,

605 
int mb_x, int mb_y, 
606 
int *mx_ptr, int *my_ptr) 
607 
{ 
608 
UINT8 *pix, *ppix; 
609 
int sum, varc, vard, mx, my, range, dmin, xx, yy;

610 
int xmin, ymin, xmax, ymax;

611 
int rel_xmin, rel_ymin, rel_xmax, rel_ymax;

612 
int pred_x=0, pred_y=0; 
613 
int P[5][2]; 
614 
const int shift= 1+s>quarter_sample; 
615 

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

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

619 
range = range * 2;

620  
621 
if (s>unrestricted_mv) {

622 
xmin = 16;

623 
ymin = 16;

624 
if (s>h263_plus)

625 
range *= 2;

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

628 
ymax = s>mb_height*16;

629 
}else {

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

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

632 
xmax = s>width; 
633 
ymax = s>height; 
634 
} 
635 
} else {

636 
xmin = 0;

637 
ymin = 0;

638 
xmax = s>mb_width*16  16; 
639 
ymax = s>mb_height*16  16; 
640 
} 
641 
switch(s>full_search) {

642 
case ME_ZERO:

643 
default:

644 
no_motion_search(s, &mx, &my); 
645 
dmin = 0;

646 
break;

647 
case ME_FULL:

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

650 
case ME_LOG:

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

652 
break;

653 
case ME_PHODS:

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

655 
break;

656 
case ME_X1: // just reserving some space for experiments ... 
657 
case ME_EPZS:

658 
rel_xmin= xmin  s>mb_x*16;

659 
rel_xmax= xmax  s>mb_x*16;

660 
rel_ymin= ymin  s>mb_y*16;

661 
rel_ymax= ymax  s>mb_y*16;

662 
if(s>out_format == FMT_H263){

663 
static const int off[4]= {2, 1, 1, 1}; 
664 
const int mot_stride = s>mb_width*2 + 2; 
665 
const int mot_xy = (s>mb_y*2 + 1)*mot_stride + s>mb_x*2 + 1; 
666 

667 
P[0][0] = s>motion_val[mot_xy ][0]; 
668 
P[0][1] = s>motion_val[mot_xy ][1]; 
669 
P[1][0] = s>motion_val[mot_xy  1][0]; 
670 
P[1][1] = s>motion_val[mot_xy  1][1]; 
671 
if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift); 
672  
673 
/* special case for first line */

674 
if ((s>mb_y == 0  s>first_slice_line  s>first_gob_line)) { 
675 
pred_x = P[1][0]; 
676 
pred_y = P[1][1]; 
677 
} else {

678 
P[2][0] = s>motion_val[mot_xy  mot_stride ][0]; 
679 
P[2][1] = s>motion_val[mot_xy  mot_stride ][1]; 
680 
P[3][0] = s>motion_val[mot_xy  mot_stride + off[0] ][0]; 
681 
P[3][1] = s>motion_val[mot_xy  mot_stride + off[0] ][1]; 
682 
if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift); 
683 
if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift); 
684 
if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift); 
685 

686 
P[4][0]= pred_x = mid_pred(P[1][0], P[2][0], P[3][0]); 
687 
P[4][1]= pred_y = mid_pred(P[1][1], P[2][1], P[3][1]); 
688 
} 
689 
}else {

690 
const int xy= s>mb_y*s>mb_width + s>mb_x; 
691 
pred_x= s>last_mv[0][0][0]; 
692 
pred_y= s>last_mv[0][0][1]; 
693  
694 
P[0][0]= s>mv_table[0][xy ]; 
695 
P[0][1]= s>mv_table[1][xy ]; 
696 
if(s>mb_x == 0){ 
697 
P[1][0]= 0; 
698 
P[1][1]= 0; 
699 
}else{

700 
P[1][0]= s>mv_table[0][xy1]; 
701 
P[1][1]= s>mv_table[1][xy1]; 
702 
if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift); 
703 
} 
704 

705 
if (!(s>mb_y == 0  s>first_slice_line  s>first_gob_line)) { 
706 
P[2][0] = s>mv_table[0][xy  s>mb_width]; 
707 
P[2][1] = s>mv_table[1][xy  s>mb_width]; 
708 
P[3][0] = s>mv_table[0][xy  s>mb_width+1]; 
709 
P[3][1] = s>mv_table[1][xy  s>mb_width+1]; 
710 
if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift); 
711 
if(P[3][0] > (rel_xmax<<shift)) P[3][0]= (rel_xmax<<shift); 
712 
if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift); 
713 
if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift); 
714 

715 
P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); 
716 
P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]); 
717 
} 
718 
} 
719 
dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); 
720 

721 
mx+= s>mb_x*16;

722 
my+= s>mb_y*16;

723 
break;

724 
} 
725  
726 
/* intra / predictive decision */

727 
xx = mb_x * 16;

728 
yy = mb_y * 16;

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

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

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

733  
734 
sum = pix_sum(pix, s>linesize); 
735 
varc = pix_norm1(pix, s>linesize); 
736 
vard = pix_norm(pix, ppix, s>linesize); 
737  
738 
vard = vard >> 8;

739 
sum = sum >> 8;

740 
varc = (varc >> 8)  (sum * sum);

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) { 
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
