Mercurial > libavcodec.hg
comparison motion_est.c @ 294:944632089814 libavcodec
4MV motion estimation (not finished yet)
SAD functions rewritten (8x8 support & MMX2 optimizations)
HQ inter/intra decission
msmpeg4 encoding bugfix (MV where too long)
author | michaelni |
---|---|
date | Wed, 27 Mar 2002 21:25:22 +0000 |
parents | 648e9245546d |
children | 6622b0fd036c |
comparison
equal
deleted
inserted
replaced
293:6eaf5da091fa | 294:944632089814 |
---|---|
24 #include "avcodec.h" | 24 #include "avcodec.h" |
25 #include "dsputil.h" | 25 #include "dsputil.h" |
26 #include "mpegvideo.h" | 26 #include "mpegvideo.h" |
27 | 27 |
28 #define ABS(a) ((a)>0 ? (a) : -(a)) | 28 #define ABS(a) ((a)>0 ? (a) : -(a)) |
29 #define MAX(a,b) ((a) > (b) ? (a) : (b)) | |
29 #define INTER_BIAS 257 | 30 #define INTER_BIAS 257 |
30 | 31 |
31 static void halfpel_motion_search(MpegEncContext * s, | 32 static void halfpel_motion_search(MpegEncContext * s, |
32 int *mx_ptr, int *my_ptr, int dmin, | 33 int *mx_ptr, int *my_ptr, int dmin, |
33 int xmin, int ymin, int xmax, int ymax, | 34 int xmin, int ymin, int xmax, int ymax, |
162 mx = 0; | 163 mx = 0; |
163 my = 0; | 164 my = 0; |
164 for (y = y1; y <= y2; y++) { | 165 for (y = y1; y <= y2; y++) { |
165 for (x = x1; x <= x2; x++) { | 166 for (x = x1; x <= x2; x++) { |
166 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, | 167 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, |
167 s->linesize, 16); | 168 s->linesize); |
168 if (d < dmin || | 169 if (d < dmin || |
169 (d == dmin && | 170 (d == dmin && |
170 (abs(x - xx) + abs(y - yy)) < | 171 (abs(x - xx) + abs(y - yy)) < |
171 (abs(mx - xx) + abs(my - yy)))) { | 172 (abs(mx - xx) + abs(my - yy)))) { |
172 dmin = d; | 173 dmin = d; |
226 my = 0; | 227 my = 0; |
227 | 228 |
228 do { | 229 do { |
229 for (y = y1; y <= y2; y += range) { | 230 for (y = y1; y <= y2; y += range) { |
230 for (x = x1; x <= x2; x += range) { | 231 for (x = x1; x <= x2; x += range) { |
231 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16); | 232 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); |
232 if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | 233 if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { |
233 dmin = d; | 234 dmin = d; |
234 mx = x; | 235 mx = x; |
235 my = y; | 236 my = y; |
236 } | 237 } |
306 dminx = 0x7fffffff; | 307 dminx = 0x7fffffff; |
307 dminy = 0x7fffffff; | 308 dminy = 0x7fffffff; |
308 | 309 |
309 lastx = x; | 310 lastx = x; |
310 for (x = x1; x <= x2; x += range) { | 311 for (x = x1; x <= x2; x += range) { |
311 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16); | 312 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); |
312 if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | 313 if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { |
313 dminx = d; | 314 dminx = d; |
314 mx = x; | 315 mx = x; |
315 } | 316 } |
316 } | 317 } |
317 | 318 |
318 x = lastx; | 319 x = lastx; |
319 for (y = y1; y <= y2; y += range) { | 320 for (y = y1; y <= y2; y += range) { |
320 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16); | 321 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); |
321 if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { | 322 if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { |
322 dminy = d; | 323 dminy = d; |
323 my = y; | 324 my = y; |
324 } | 325 } |
325 } | 326 } |
359 | 360 |
360 #define Z_THRESHOLD 256 | 361 #define Z_THRESHOLD 256 |
361 | 362 |
362 #define CHECK_MV(x,y)\ | 363 #define CHECK_MV(x,y)\ |
363 {\ | 364 {\ |
364 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\ | 365 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\ |
365 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ | 366 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ |
366 if(d<dmin){\ | 367 if(d<dmin){\ |
367 best[0]=x;\ | 368 best[0]=x;\ |
368 best[1]=y;\ | 369 best[1]=y;\ |
369 dmin=d;\ | 370 dmin=d;\ |
370 }\ | 371 }\ |
371 } | 372 } |
372 | 373 |
373 #define CHECK_MV_DIR(x,y,new_dir)\ | 374 #define CHECK_MV_DIR(x,y,new_dir)\ |
374 {\ | 375 {\ |
375 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\ | 376 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\ |
376 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ | 377 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ |
377 if(d<dmin){\ | 378 if(d<dmin){\ |
378 best[0]=x;\ | 379 best[0]=x;\ |
379 best[1]=y;\ | 380 best[1]=y;\ |
380 dmin=d;\ | 381 dmin=d;\ |
381 next_dir= new_dir;\ | 382 next_dir= new_dir;\ |
382 }\ | 383 }\ |
383 } | 384 } |
385 | |
386 #define CHECK_MV4(x,y)\ | |
387 {\ | |
388 d = pix_abs8x8(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\ | |
389 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ | |
390 if(d<dmin){\ | |
391 best[0]=x;\ | |
392 best[1]=y;\ | |
393 dmin=d;\ | |
394 }\ | |
395 } | |
396 | |
397 #define CHECK_MV4_DIR(x,y,new_dir)\ | |
398 {\ | |
399 d = pix_abs8x8(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\ | |
400 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\ | |
401 if(d<dmin){\ | |
402 best[0]=x;\ | |
403 best[1]=y;\ | |
404 dmin=d;\ | |
405 next_dir= new_dir;\ | |
406 }\ | |
407 } | |
408 | |
384 | 409 |
385 #define check(x,y,S,v)\ | 410 #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);\ | 411 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);\ | 412 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);\ | 413 if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s->mb_x, s->mb_y);\ |
438 if(dmin==last_min) return dmin; | 463 if(dmin==last_min) return dmin; |
439 } | 464 } |
440 */ | 465 */ |
441 } | 466 } |
442 | 467 |
468 static inline int small_diamond_search4MV(MpegEncContext * s, int *best, int dmin, | |
469 UINT8 *new_pic, UINT8 *old_pic, int pic_stride, | |
470 int pred_x, int pred_y, UINT16 *mv_penalty, int quant, | |
471 int xmin, int ymin, int xmax, int ymax, int shift) | |
472 { | |
473 int next_dir=-1; | |
474 | |
475 for(;;){ | |
476 int d; | |
477 const int dir= next_dir; | |
478 const int x= best[0]; | |
479 const int y= best[1]; | |
480 next_dir=-1; | |
481 | |
482 //printf("%d", dir); | |
483 if(dir!=2 && x>xmin) CHECK_MV4_DIR(x-1, y , 0) | |
484 if(dir!=3 && y>ymin) CHECK_MV4_DIR(x , y-1, 1) | |
485 if(dir!=0 && x<xmax) CHECK_MV4_DIR(x+1, y , 2) | |
486 if(dir!=1 && y<ymax) CHECK_MV4_DIR(x , y+1, 3) | |
487 | |
488 if(next_dir==-1){ | |
489 return dmin; | |
490 } | |
491 } | |
492 } | |
493 | |
443 static inline int snake_search(MpegEncContext * s, int *best, int dmin, | 494 static inline int snake_search(MpegEncContext * s, int *best, int dmin, |
444 UINT8 *new_pic, UINT8 *old_pic, int pic_stride, | 495 UINT8 *new_pic, UINT8 *old_pic, int pic_stride, |
445 int pred_x, int pred_y, UINT16 *mv_penalty, int quant, | 496 int pred_x, int pred_y, UINT16 *mv_penalty, int quant, |
446 int xmin, int ymin, int xmax, int ymax, int shift) | 497 int xmin, int ymin, int xmax, int ymax, int shift) |
447 { | 498 { |
467 int y= best[1]; | 518 int y= best[1]; |
468 int d; | 519 int d; |
469 x+=x_dir[dir]; | 520 x+=x_dir[dir]; |
470 y+=y_dir[dir]; | 521 y+=y_dir[dir]; |
471 if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){ | 522 if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){ |
472 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16); | 523 d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride); |
473 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant; | 524 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant; |
474 }else{ | 525 }else{ |
475 d = dmin + 10000; //FIXME smarter boundary handling | 526 d = dmin + 10000; //FIXME smarter boundary handling |
476 } | 527 } |
477 if(d<dmin){ | 528 if(d<dmin){ |
515 const int shift= 1+s->quarter_sample; | 566 const int shift= 1+s->quarter_sample; |
516 | 567 |
517 new_pic = s->new_picture[0] + pic_xy; | 568 new_pic = s->new_picture[0] + pic_xy; |
518 old_pic = s->last_picture[0] + pic_xy; | 569 old_pic = s->last_picture[0] + pic_xy; |
519 | 570 |
520 dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16); | 571 dmin = pix_abs16x16(new_pic, old_pic, pic_stride); |
521 if(dmin<Z_THRESHOLD){ | 572 if(dmin<Z_THRESHOLD){ |
522 *mx_ptr= 0; | 573 *mx_ptr= 0; |
523 *my_ptr= 0; | 574 *my_ptr= 0; |
524 //printf("Z"); | 575 //printf("Z"); |
525 return dmin; | 576 return dmin; |
555 | 606 |
556 // printf("%d %d %d \n", best[0], best[1], dmin); | 607 // printf("%d %d %d \n", best[0], best[1], dmin); |
557 return dmin; | 608 return dmin; |
558 } | 609 } |
559 | 610 |
611 static int epzs_motion_search4(MpegEncContext * s, int block, | |
612 int *mx_ptr, int *my_ptr, | |
613 int P[6][2], int pred_x, int pred_y, | |
614 int xmin, int ymin, int xmax, int ymax) | |
615 { | |
616 int best[2]={0, 0}; | |
617 int d, dmin; | |
618 UINT8 *new_pic, *old_pic; | |
619 const int pic_stride= s->linesize; | |
620 const int pic_xy= ((s->mb_y*2 + (block>>1))*pic_stride + s->mb_x*2 + (block&1))*8; | |
621 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame | |
622 int quant= s->qscale; // qscale of the prev frame | |
623 const int shift= 1+s->quarter_sample; | |
624 | |
625 new_pic = s->new_picture[0] + pic_xy; | |
626 old_pic = s->last_picture[0] + pic_xy; | |
627 | |
628 dmin = pix_abs8x8(new_pic, old_pic, pic_stride); | |
629 | |
630 /* first line */ | |
631 if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line) && block<2) { | |
632 CHECK_MV4(P[1][0]>>shift, P[1][1]>>shift) | |
633 }else{ | |
634 CHECK_MV4(P[4][0]>>shift, P[4][1]>>shift) | |
635 if(dmin<Z_THRESHOLD){ | |
636 *mx_ptr= P[4][0]>>shift; | |
637 *my_ptr= P[4][1]>>shift; | |
638 //printf("M\n"); | |
639 return dmin; | |
640 } | |
641 CHECK_MV4(P[1][0]>>shift, P[1][1]>>shift) | |
642 CHECK_MV4(P[2][0]>>shift, P[2][1]>>shift) | |
643 CHECK_MV4(P[3][0]>>shift, P[3][1]>>shift) | |
644 } | |
645 CHECK_MV4(P[0][0]>>shift, P[0][1]>>shift) | |
646 CHECK_MV4(P[5][0]>>shift, P[5][1]>>shift) | |
647 | |
648 //check(best[0],best[1],0, b0) | |
649 dmin= small_diamond_search4MV(s, best, dmin, new_pic, old_pic, pic_stride, | |
650 pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift); | |
651 //check(best[0],best[1],0, b1) | |
652 *mx_ptr= best[0]; | |
653 *my_ptr= best[1]; | |
654 | |
655 // printf("%d %d %d \n", best[0], best[1], dmin); | |
656 return dmin; | |
657 } | |
658 | |
560 #define CHECK_HALF_MV(suffix, x, y) \ | 659 #define CHECK_HALF_MV(suffix, x, y) \ |
561 d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\ | 660 d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize);\ |
562 d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\ | 661 d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\ |
563 if(d<dminh){\ | 662 if(d<dminh){\ |
564 dminh= d;\ | 663 dminh= d;\ |
565 mx= mx1 + x;\ | 664 mx= mx1 + x;\ |
566 my= my1 + y;\ | 665 my= my1 + y;\ |
567 } | 666 } |
568 | 667 |
668 #define CHECK_HALF_MV4(suffix, x, y) \ | |
669 d= pix_abs8x8_ ## suffix(pix, ptr+((x)>>1), s->linesize);\ | |
670 d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\ | |
671 if(d<dminh){\ | |
672 dminh= d;\ | |
673 mx= mx1 + x;\ | |
674 my= my1 + y;\ | |
675 } | |
676 | |
569 /* The idea would be to make half pel ME after Inter/Intra decision to | 677 /* The idea would be to make half pel ME after Inter/Intra decision to |
570 save time. */ | 678 save time. */ |
571 static inline void halfpel_motion_search(MpegEncContext * s, | 679 static inline void halfpel_motion_search(MpegEncContext * s, |
572 int *mx_ptr, int *my_ptr, int dmin, | 680 int *mx_ptr, int *my_ptr, int dmin, |
573 int xmin, int ymin, int xmax, int ymax, | 681 int xmin, int ymin, int xmax, int ymax, |
612 CHECK_HALF_MV(x2 , -1, 0) | 720 CHECK_HALF_MV(x2 , -1, 0) |
613 CHECK_HALF_MV(x2 , +1, 0) | 721 CHECK_HALF_MV(x2 , +1, 0) |
614 CHECK_HALF_MV(xy2, -1, +1) | 722 CHECK_HALF_MV(xy2, -1, +1) |
615 CHECK_HALF_MV(y2 , 0, +1) | 723 CHECK_HALF_MV(y2 , 0, +1) |
616 CHECK_HALF_MV(xy2, +1, +1) | 724 CHECK_HALF_MV(xy2, +1, +1) |
725 | |
617 }else{ | 726 }else{ |
618 mx= 2*(mx - xx); | 727 mx= 2*(mx - xx); |
619 my= 2*(my - yy); | 728 my= 2*(my - yy); |
620 } | 729 } |
621 | 730 |
622 *mx_ptr = mx; | 731 *mx_ptr = mx; |
623 *my_ptr = my; | 732 *my_ptr = my; |
624 } | 733 } |
625 | 734 |
735 static inline void halfpel_motion_search4(MpegEncContext * s, | |
736 int *mx_ptr, int *my_ptr, int dmin, | |
737 int xmin, int ymin, int xmax, int ymax, | |
738 int pred_x, int pred_y, int block_x, int block_y) | |
739 { | |
740 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame | |
741 const int quant= s->qscale; | |
742 int pen_x, pen_y; | |
743 int mx, my, mx1, my1, d, xx, yy, dminh; | |
744 UINT8 *pix, *ptr; | |
745 | |
746 xx = 8 * block_x; | |
747 yy = 8 * block_y; | |
748 pix = s->new_picture[0] + (yy * s->linesize) + xx; | |
749 | |
750 mx = *mx_ptr; | |
751 my = *my_ptr; | |
752 ptr = s->last_picture[0] + ((yy+my) * s->linesize) + xx + mx; | |
753 | |
754 dminh = dmin; | |
755 | |
756 if (mx > xmin && mx < xmax && | |
757 my > ymin && my < ymax) { | |
758 | |
759 mx= mx1= 2*mx; | |
760 my= my1= 2*my; | |
761 if(dmin < Z_THRESHOLD && mx==0 && my==0){ | |
762 *mx_ptr = 0; | |
763 *my_ptr = 0; | |
764 return; | |
765 } | |
766 | |
767 pen_x= pred_x + mx; | |
768 pen_y= pred_y + my; | |
769 | |
770 ptr-= s->linesize; | |
771 CHECK_HALF_MV4(xy2, -1, -1) | |
772 CHECK_HALF_MV4(y2 , 0, -1) | |
773 CHECK_HALF_MV4(xy2, +1, -1) | |
774 | |
775 ptr+= s->linesize; | |
776 CHECK_HALF_MV4(x2 , -1, 0) | |
777 CHECK_HALF_MV4(x2 , +1, 0) | |
778 CHECK_HALF_MV4(xy2, -1, +1) | |
779 CHECK_HALF_MV4(y2 , 0, +1) | |
780 CHECK_HALF_MV4(xy2, +1, +1) | |
781 | |
782 }else{ | |
783 mx*=2; | |
784 my*=2; | |
785 } | |
786 | |
787 *mx_ptr = mx; | |
788 *my_ptr = my; | |
789 } | |
790 | |
791 static inline void set_mv_tables(MpegEncContext * s, int mx, int my) | |
792 { | |
793 const int xy= s->mb_x + s->mb_y*s->mb_width; | |
794 | |
795 s->mv_table[0][xy] = mx; | |
796 s->mv_table[1][xy] = my; | |
797 | |
798 /* has allready been set to the 4 MV if 4MV is done */ | |
799 if(!(s->flags&CODEC_FLAG_4MV)){ | |
800 int mot_xy= s->block_index[0]; | |
801 | |
802 s->motion_val[mot_xy ][0]= mx; | |
803 s->motion_val[mot_xy ][1]= my; | |
804 s->motion_val[mot_xy+1][0]= mx; | |
805 s->motion_val[mot_xy+1][1]= my; | |
806 | |
807 mot_xy += s->block_wrap[0]; | |
808 s->motion_val[mot_xy ][0]= mx; | |
809 s->motion_val[mot_xy ][1]= my; | |
810 s->motion_val[mot_xy+1][0]= mx; | |
811 s->motion_val[mot_xy+1][1]= my; | |
812 } | |
813 } | |
814 | |
626 #ifndef CONFIG_TEST_MV_ENCODE | 815 #ifndef CONFIG_TEST_MV_ENCODE |
627 | 816 |
628 int estimate_motion(MpegEncContext * s, | 817 void estimate_motion(MpegEncContext * s, |
629 int mb_x, int mb_y, | 818 int mb_x, int mb_y) |
630 int *mx_ptr, int *my_ptr) | |
631 { | 819 { |
632 UINT8 *pix, *ppix; | 820 UINT8 *pix, *ppix; |
633 int sum, varc, vard, mx, my, range, dmin, xx, yy; | 821 int sum, varc, vard, mx, my, range, dmin, xx, yy; |
634 int xmin, ymin, xmax, ymax; | 822 int xmin, ymin, xmax, ymax; |
635 int rel_xmin, rel_ymin, rel_xmax, rel_ymax; | 823 int rel_xmin, rel_ymin, rel_xmax, rel_ymax; |
636 int pred_x=0, pred_y=0; | 824 int pred_x=0, pred_y=0; |
637 int P[5][2]; | 825 int P[6][2]; |
638 const int shift= 1+s->quarter_sample; | 826 const int shift= 1+s->quarter_sample; |
827 int mb_type=0; | |
639 | 828 |
640 range = 8 * (1 << (s->f_code - 1)); | 829 range = 8 * (1 << (s->f_code - 1)); |
641 /* XXX: temporary kludge to avoid overflow for msmpeg4 */ | 830 /* XXX: temporary kludge to avoid overflow for msmpeg4 */ |
642 if (s->out_format == FMT_H263 && !s->h263_msmpeg4) | 831 if (s->out_format == FMT_H263 && !s->h263_msmpeg4) |
643 range = range * 2; | 832 range = range * 2; |
678 dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax); | 867 dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax); |
679 break; | 868 break; |
680 case ME_X1: | 869 case ME_X1: |
681 case ME_EPZS: | 870 case ME_EPZS: |
682 { | 871 { |
683 static const int off[4]= {2, 1, 1, -1}; | 872 const int mot_stride = s->block_wrap[0]; |
684 const int mot_stride = s->mb_width*2 + 2; | 873 const int mot_xy = s->block_index[0]; |
685 const int mot_xy = (s->mb_y*2 + 1)*mot_stride + s->mb_x*2 + 1; | 874 |
686 | 875 rel_xmin= xmin - mb_x*16; |
687 rel_xmin= xmin - s->mb_x*16; | 876 rel_xmax= xmax - mb_x*16; |
688 rel_xmax= xmax - s->mb_x*16; | 877 rel_ymin= ymin - mb_y*16; |
689 rel_ymin= ymin - s->mb_y*16; | 878 rel_ymax= ymax - mb_y*16; |
690 rel_ymax= ymax - s->mb_y*16; | |
691 | 879 |
692 P[0][0] = s->motion_val[mot_xy ][0]; | 880 P[0][0] = s->motion_val[mot_xy ][0]; |
693 P[0][1] = s->motion_val[mot_xy ][1]; | 881 P[0][1] = s->motion_val[mot_xy ][1]; |
694 P[1][0] = s->motion_val[mot_xy - 1][0]; | 882 P[1][0] = s->motion_val[mot_xy - 1][0]; |
695 P[1][1] = s->motion_val[mot_xy - 1][1]; | 883 P[1][1] = s->motion_val[mot_xy - 1][1]; |
696 if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift); | 884 if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift); |
697 | 885 |
698 /* special case for first line */ | 886 /* special case for first line */ |
699 if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) { | 887 if ((mb_y == 0 || s->first_slice_line || s->first_gob_line)) { |
700 P[4][0] = P[1][0]; | 888 P[4][0] = P[1][0]; |
701 P[4][1] = P[1][1]; | 889 P[4][1] = P[1][1]; |
702 } else { | 890 } else { |
703 P[2][0] = s->motion_val[mot_xy - mot_stride ][0]; | 891 P[2][0] = s->motion_val[mot_xy - mot_stride ][0]; |
704 P[2][1] = s->motion_val[mot_xy - mot_stride ][1]; | 892 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]; | 893 P[3][0] = s->motion_val[mot_xy - mot_stride + 2 ][0]; |
706 P[3][1] = s->motion_val[mot_xy - mot_stride + off[0] ][1]; | 894 P[3][1] = s->motion_val[mot_xy - mot_stride + 2 ][1]; |
707 if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift); | 895 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); | 896 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); | 897 if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift); |
710 | 898 |
711 P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); | 899 P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); |
719 pred_y= P[1][1]; | 907 pred_y= P[1][1]; |
720 } | 908 } |
721 } | 909 } |
722 dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); | 910 dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); |
723 | 911 |
724 mx+= s->mb_x*16; | 912 mx+= mb_x*16; |
725 my+= s->mb_y*16; | 913 my+= mb_y*16; |
726 break; | 914 break; |
915 } | |
916 | |
917 if(s->flags&CODEC_FLAG_4MV){ | |
918 int block; | |
919 | |
920 mb_type|= MB_TYPE_INTER4V; | |
921 | |
922 for(block=0; block<4; block++){ | |
923 int mx4, my4; | |
924 int pred_x4, pred_y4; | |
925 int dmin4; | |
926 static const int off[4]= {2, 1, 1, -1}; | |
927 const int mot_stride = s->block_wrap[0]; | |
928 const int mot_xy = s->block_index[block]; | |
929 const int block_x= mb_x*2 + (block&1); | |
930 const int block_y= mb_y*2 + (block>>1); | |
931 | |
932 const int rel_xmin4= xmin - block_x*8; | |
933 const int rel_xmax4= xmax - block_x*8; | |
934 const int rel_ymin4= ymin - block_y*8; | |
935 const int rel_ymax4= ymax - block_y*8; | |
936 | |
937 P[0][0] = s->motion_val[mot_xy ][0]; | |
938 P[0][1] = s->motion_val[mot_xy ][1]; | |
939 P[1][0] = s->motion_val[mot_xy - 1][0]; | |
940 P[1][1] = s->motion_val[mot_xy - 1][1]; | |
941 if(P[1][0] > (rel_xmax4<<shift)) P[1][0]= (rel_xmax4<<shift); | |
942 | |
943 /* special case for first line */ | |
944 if ((mb_y == 0 || s->first_slice_line || s->first_gob_line) && block<2) { | |
945 P[4][0] = P[1][0]; | |
946 P[4][1] = P[1][1]; | |
947 } else { | |
948 P[2][0] = s->motion_val[mot_xy - mot_stride ][0]; | |
949 P[2][1] = s->motion_val[mot_xy - mot_stride ][1]; | |
950 P[3][0] = s->motion_val[mot_xy - mot_stride + off[block]][0]; | |
951 P[3][1] = s->motion_val[mot_xy - mot_stride + off[block]][1]; | |
952 if(P[2][1] > (rel_ymax4<<shift)) P[2][1]= (rel_ymax4<<shift); | |
953 if(P[3][0] < (rel_xmin4<<shift)) P[3][0]= (rel_xmin4<<shift); | |
954 if(P[3][1] > (rel_ymax4<<shift)) P[3][1]= (rel_ymax4<<shift); | |
955 | |
956 P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]); | |
957 P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]); | |
958 } | |
959 if(s->out_format == FMT_H263){ | |
960 pred_x4 = P[4][0]; | |
961 pred_y4 = P[4][1]; | |
962 }else { /* mpeg1 at least */ | |
963 pred_x4= P[1][0]; | |
964 pred_y4= P[1][1]; | |
965 } | |
966 P[5][0]= mx - mb_x*16; | |
967 P[5][1]= my - mb_y*16; | |
968 | |
969 dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4); | |
970 | |
971 halfpel_motion_search4(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, | |
972 pred_x4, pred_y4, block_x, block_y); | |
973 | |
974 s->motion_val[ s->block_index[block] ][0]= mx4; | |
975 s->motion_val[ s->block_index[block] ][1]= my4; | |
976 } | |
727 } | 977 } |
728 | 978 |
729 /* intra / predictive decision */ | 979 /* intra / predictive decision */ |
730 xx = mb_x * 16; | 980 xx = mb_x * 16; |
731 yy = mb_y * 16; | 981 yy = mb_y * 16; |
735 ppix = s->last_picture[0] + (my * s->linesize) + mx; | 985 ppix = s->last_picture[0] + (my * s->linesize) + mx; |
736 | 986 |
737 sum = pix_sum(pix, s->linesize); | 987 sum = pix_sum(pix, s->linesize); |
738 #if 0 | 988 #if 0 |
739 varc = pix_dev(pix, s->linesize, (sum+128)>>8) + INTER_BIAS; | 989 varc = pix_dev(pix, s->linesize, (sum+128)>>8) + INTER_BIAS; |
740 vard = pix_abs16x16(pix, ppix, s->linesize, 16); | 990 vard = pix_abs16x16(pix, ppix, s->linesize); |
741 #else | 991 #else |
742 sum= (sum+8)>>4; | 992 sum= (sum+8)>>4; |
743 varc = ((pix_norm1(pix, s->linesize) - sum*sum + 128 + 500)>>8); | 993 varc = ((pix_norm1(pix, s->linesize) - sum*sum + 128 + 500)>>8); |
744 vard = (pix_norm(pix, ppix, s->linesize)+128)>>8; | 994 vard = (pix_norm(pix, ppix, s->linesize)+128)>>8; |
745 #endif | 995 #endif |
746 | 996 |
747 s->mb_var[s->mb_width * mb_y + mb_x] = varc; | 997 s->mb_var[s->mb_width * mb_y + mb_x] = varc; |
748 s->avg_mb_var += varc; | 998 s->avg_mb_var+= varc; |
749 s->mc_mb_var += vard; | 999 s->mc_mb_var += vard; |
750 | 1000 |
751 #if 0 | 1001 #if 0 |
752 printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n", | 1002 printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n", |
753 varc, s->avg_mb_var, sum, vard, mx - xx, my - yy); | 1003 varc, s->avg_mb_var, sum, vard, mx - xx, my - yy); |
754 #endif | 1004 #endif |
755 if (vard <= 64 || vard < varc) { | 1005 if(s->flags&CODEC_FLAG_HQ){ |
756 if (s->full_search != ME_ZERO) { | 1006 if (vard*2 + 200 > varc) |
1007 mb_type|= MB_TYPE_INTRA; | |
1008 if (varc*2 + 200 > vard){ | |
1009 mb_type|= MB_TYPE_INTER; | |
757 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); | 1010 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); |
758 } else { | 1011 } |
759 mx -= 16 * s->mb_x; | 1012 }else{ |
760 my -= 16 * s->mb_y; | 1013 if (vard <= 64 || vard < varc) { |
761 } | 1014 mb_type|= MB_TYPE_INTER; |
762 // check(mx + 32*s->mb_x, my + 32*s->mb_y, 1, end) | 1015 if (s->full_search != ME_ZERO) { |
763 | 1016 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); |
764 *mx_ptr = mx; | 1017 } else { |
765 *my_ptr = my; | 1018 mx -= 16 * mb_x; |
766 return 0; | 1019 my -= 16 * mb_y; |
767 } else { | 1020 } |
768 *mx_ptr = 0; | 1021 }else{ |
769 *my_ptr = 0; | 1022 mb_type|= MB_TYPE_INTRA; |
770 return 1; | 1023 mx = 0;//mx*2 - 32 * mb_x; |
771 } | 1024 my = 0;//my*2 - 32 * mb_y; |
1025 } | |
1026 } | |
1027 | |
1028 s->mb_type[mb_y*s->mb_width + mb_x]= mb_type; | |
1029 set_mv_tables(s, mx, my); | |
772 } | 1030 } |
773 | 1031 |
774 #else | 1032 #else |
775 | 1033 |
776 /* test version which generates valid random vectors */ | 1034 /* test version which generates valid random vectors */ |