Mercurial > libavcodec.hg
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; |