comparison motion_est.c @ 281:1fc96b02142e libavcodec

mpeg4 aspect_ratio_info in AVCodecContext (requested by alex) experimental (& faster) motion estimation squished a dirty uninitialized var bug mpeg1 fcode>1 support
author michaelni
date Fri, 22 Mar 2002 23:22:08 +0000
parents 3dc1ca4ba717
children 0778d4e1d584
comparison
equal deleted inserted replaced
280:3dc1ca4ba717 281:1fc96b02142e
333 333
334 334
335 #define Z_THRESHOLD 256 335 #define Z_THRESHOLD 256
336 336
337 #define CHECK_MV(x,y)\ 337 #define CHECK_MV(x,y)\
338 {\
338 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\ 339 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
339 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ 340 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
340 if(d<dmin){\ 341 if(d<dmin){\
341 best[0]=x;\ 342 best[0]=x;\
342 best[1]=y;\ 343 best[1]=y;\
343 dmin=d;\ 344 dmin=d;\
344 } 345 }\
346 }
345 347
346 #define CHECK_MV_DIR(x,y,new_dir)\ 348 #define CHECK_MV_DIR(x,y,new_dir)\
347 {\ 349 {\
348 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\ 350 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
349 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ 351 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
353 dmin=d;\ 355 dmin=d;\
354 next_dir= new_dir;\ 356 next_dir= new_dir;\
355 }\ 357 }\
356 } 358 }
357 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
358 static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, 367 static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
359 UINT8 *new_pic, UINT8 *old_pic, int pic_stride, 368 UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
360 int pred_x, int pred_y, UINT16 *mv_penalty, int quant, 369 int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
361 int xmin, int ymin, int xmax, int ymax, int shift) 370 int xmin, int ymin, int xmax, int ymax, int shift)
362 { 371 {
376 if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3) 385 if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
377 386
378 if(next_dir==-1){ 387 if(next_dir==-1){
379 return dmin; 388 return dmin;
380 } 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(x-1, y )
398 if(y>xmin) CHECK_MV(x , y-1)
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(x-1, y-1)
402 if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
403 if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
404 if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
405 if(x-1>xmin) CHECK_MV(x-2, y )
406 if(y-1>xmin) CHECK_MV(x , y-2)
407 if(x+1<xmax) CHECK_MV(x+2, y )
408 if(y+1<xmax) CHECK_MV(x , y+2)
409 if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
410 if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
411 if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
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;
381 } 475 }
382 } 476 }
383 477
384 static int epzs_motion_search(MpegEncContext * s, 478 static int epzs_motion_search(MpegEncContext * s,
385 int *mx_ptr, int *my_ptr, 479 int *mx_ptr, int *my_ptr,
395 int quant= s->qscale; // qscale of the prev frame 489 int quant= s->qscale; // qscale of the prev frame
396 const int shift= 1+s->quarter_sample; 490 const int shift= 1+s->quarter_sample;
397 491
398 new_pic = s->new_picture[0] + pic_xy; 492 new_pic = s->new_picture[0] + pic_xy;
399 old_pic = s->last_picture[0] + pic_xy; 493 old_pic = s->last_picture[0] + pic_xy;
400 //printf("%d %d %d %d\n", xmin, ymin, xmax, ymax); 494
401
402 dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16); 495 dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);
403 if(dmin<Z_THRESHOLD){ 496 if(dmin<Z_THRESHOLD){
404 *mx_ptr= 0; 497 *mx_ptr= 0;
405 *my_ptr= 0; 498 *my_ptr= 0;
406 //printf("Z"); 499 //printf("Z");
422 CHECK_MV(P[2][0]>>shift, P[2][1]>>shift) 515 CHECK_MV(P[2][0]>>shift, P[2][1]>>shift)
423 CHECK_MV(P[3][0]>>shift, P[3][1]>>shift) 516 CHECK_MV(P[3][0]>>shift, P[3][1]>>shift)
424 } 517 }
425 CHECK_MV(P[0][0]>>shift, P[0][1]>>shift) 518 CHECK_MV(P[0][0]>>shift, P[0][1]>>shift)
426 519
427 dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 520 //check(best[0],best[1],0, b0)
428 pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); 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)
429 *mx_ptr= best[0]; 528 *mx_ptr= best[0];
430 *my_ptr= best[1]; 529 *my_ptr= best[1];
431 530
432 // printf("%d %d %d \n", best[0], best[1], dmin); 531 // printf("%d %d %d \n", best[0], best[1], dmin);
433
434 return dmin; 532 return dmin;
435 } 533 }
436 534
437 #define CHECK_HALF_MV(suffix, x, y) \ 535 #define CHECK_HALF_MV(suffix, x, y) \
438 d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\ 536 d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\
561 rel_xmax= xmax - s->mb_x*16; 659 rel_xmax= xmax - s->mb_x*16;
562 rel_ymin= ymin - s->mb_y*16; 660 rel_ymin= ymin - s->mb_y*16;
563 rel_ymax= ymax - s->mb_y*16; 661 rel_ymax= ymax - s->mb_y*16;
564 if(s->out_format == FMT_H263){ 662 if(s->out_format == FMT_H263){
565 static const int off[4]= {2, 1, 1, -1}; 663 static const int off[4]= {2, 1, 1, -1};
566 const int mot_stride = s->block_wrap[0]; 664 const int mot_stride = s->mb_width*2 + 2;
567 const int mot_xy = s->block_index[0]; 665 const int mot_xy = (s->mb_y*2 + 1)*mot_stride + s->mb_x*2 + 1;
568 666
569 P[0][0] = s->motion_val[mot_xy ][0]; 667 P[0][0] = s->motion_val[mot_xy ][0];
570 P[0][1] = s->motion_val[mot_xy ][1]; 668 P[0][1] = s->motion_val[mot_xy ][1];
571 P[1][0] = s->motion_val[mot_xy - 1][0]; 669 P[1][0] = s->motion_val[mot_xy - 1][0];
572 P[1][1] = s->motion_val[mot_xy - 1][1]; 670 P[1][1] = s->motion_val[mot_xy - 1][1];
616 714
617 P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); 715 P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]);
618 P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]); 716 P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]);
619 } 717 }
620 } 718 }
621 dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); 719 dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax);
720
622 mx+= s->mb_x*16; 721 mx+= s->mb_x*16;
623 my+= s->mb_y*16; 722 my+= s->mb_y*16;
624 break; 723 break;
625 } 724 }
626 725
652 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); 751 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y);
653 } else { 752 } else {
654 mx -= 16 * s->mb_x; 753 mx -= 16 * s->mb_x;
655 my -= 16 * s->mb_y; 754 my -= 16 * s->mb_y;
656 } 755 }
756 // check(mx + 32*s->mb_x, my + 32*s->mb_y, 1, end)
757
657 *mx_ptr = mx; 758 *mx_ptr = mx;
658 *my_ptr = my; 759 *my_ptr = my;
659 return 0; 760 return 0;
660 } else { 761 } else {
661 *mx_ptr = 0; 762 *mx_ptr = 0;