comparison motion_est.c @ 324:9c6f056f0e41 libavcodec

fixed mpeg4 time stuff on encoding mpeg4 b-frame enoding support removed old, out-commented ratecontrol reuse motion compensation code between encoding & decoding prefix newly added global functions with ff_ to reduce namespace polution b-frame ME (unfinished, but working) added some comments to mpegvideo.h do MC on encoding only once if possible bugs? ;)
author michaelni
date Wed, 17 Apr 2002 04:32:12 +0000
parents cda7d0857baf
children d359db02fc90
comparison
equal deleted inserted replaced
323:68cc7650c645 324:9c6f056f0e41
30 #define INTER_BIAS 257 30 #define INTER_BIAS 257
31 31
32 static void halfpel_motion_search(MpegEncContext * s, 32 static void halfpel_motion_search(MpegEncContext * s,
33 int *mx_ptr, int *my_ptr, int dmin, 33 int *mx_ptr, int *my_ptr, int dmin,
34 int xmin, int ymin, int xmax, int ymax, 34 int xmin, int ymin, int xmax, int ymax,
35 int pred_x, int pred_y); 35 int pred_x, int pred_y, uint8_t *ref_picture);
36
37 /* config it to test motion vector encoding (send random vectors) */
38 //#define CONFIG_TEST_MV_ENCODE
39 36
40 static int pix_sum(UINT8 * pix, int line_size) 37 static int pix_sum(UINT8 * pix, int line_size)
41 { 38 {
42 int s, i, j; 39 int s, i, j;
43 40
136 *my_ptr = 16 * s->mb_y; 133 *my_ptr = 16 * s->mb_y;
137 } 134 }
138 135
139 static int full_motion_search(MpegEncContext * s, 136 static int full_motion_search(MpegEncContext * s,
140 int *mx_ptr, int *my_ptr, int range, 137 int *mx_ptr, int *my_ptr, int range,
141 int xmin, int ymin, int xmax, int ymax) 138 int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
142 { 139 {
143 int x1, y1, x2, y2, xx, yy, x, y; 140 int x1, y1, x2, y2, xx, yy, x, y;
144 int mx, my, dmin, d; 141 int mx, my, dmin, d;
145 UINT8 *pix; 142 UINT8 *pix;
146 143
162 dmin = 0x7fffffff; 159 dmin = 0x7fffffff;
163 mx = 0; 160 mx = 0;
164 my = 0; 161 my = 0;
165 for (y = y1; y <= y2; y++) { 162 for (y = y1; y <= y2; y++) {
166 for (x = x1; x <= x2; x++) { 163 for (x = x1; x <= x2; x++) {
167 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, 164 d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x,
168 s->linesize); 165 s->linesize);
169 if (d < dmin || 166 if (d < dmin ||
170 (d == dmin && 167 (d == dmin &&
171 (abs(x - xx) + abs(y - yy)) < 168 (abs(x - xx) + abs(y - yy)) <
172 (abs(mx - xx) + abs(my - yy)))) { 169 (abs(mx - xx) + abs(my - yy)))) {
190 } 187 }
191 188
192 189
193 static int log_motion_search(MpegEncContext * s, 190 static int log_motion_search(MpegEncContext * s,
194 int *mx_ptr, int *my_ptr, int range, 191 int *mx_ptr, int *my_ptr, int range,
195 int xmin, int ymin, int xmax, int ymax) 192 int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
196 { 193 {
197 int x1, y1, x2, y2, xx, yy, x, y; 194 int x1, y1, x2, y2, xx, yy, x, y;
198 int mx, my, dmin, d; 195 int mx, my, dmin, d;
199 UINT8 *pix; 196 UINT8 *pix;
200 197
227 my = 0; 224 my = 0;
228 225
229 do { 226 do {
230 for (y = y1; y <= y2; y += range) { 227 for (y = y1; y <= y2; y += range) {
231 for (x = x1; x <= x2; x += range) { 228 for (x = x1; x <= x2; x += range) {
232 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); 229 d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
233 if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { 230 if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
234 dmin = d; 231 dmin = d;
235 mx = x; 232 mx = x;
236 my = y; 233 my = y;
237 } 234 }
266 return dmin; 263 return dmin;
267 } 264 }
268 265
269 static int phods_motion_search(MpegEncContext * s, 266 static int phods_motion_search(MpegEncContext * s,
270 int *mx_ptr, int *my_ptr, int range, 267 int *mx_ptr, int *my_ptr, int range,
271 int xmin, int ymin, int xmax, int ymax) 268 int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
272 { 269 {
273 int x1, y1, x2, y2, xx, yy, x, y, lastx, d; 270 int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
274 int mx, my, dminx, dminy; 271 int mx, my, dminx, dminy;
275 UINT8 *pix; 272 UINT8 *pix;
276 273
307 dminx = 0x7fffffff; 304 dminx = 0x7fffffff;
308 dminy = 0x7fffffff; 305 dminy = 0x7fffffff;
309 306
310 lastx = x; 307 lastx = x;
311 for (x = x1; x <= x2; x += range) { 308 for (x = x1; x <= x2; x += range) {
312 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); 309 d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
313 if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { 310 if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
314 dminx = d; 311 dminx = d;
315 mx = x; 312 mx = x;
316 } 313 }
317 } 314 }
318 315
319 x = lastx; 316 x = lastx;
320 for (y = y1; y <= y2; y += range) { 317 for (y = y1; y <= y2; y += range) {
321 d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize); 318 d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
322 if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) { 319 if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
323 dminy = d; 320 dminy = d;
324 my = y; 321 my = y;
325 } 322 }
326 } 323 }
552 } 549 }
553 550
554 static int epzs_motion_search(MpegEncContext * s, 551 static int epzs_motion_search(MpegEncContext * s,
555 int *mx_ptr, int *my_ptr, 552 int *mx_ptr, int *my_ptr,
556 int P[5][2], int pred_x, int pred_y, 553 int P[5][2], int pred_x, int pred_y,
557 int xmin, int ymin, int xmax, int ymax) 554 int xmin, int ymin, int xmax, int ymax, uint8_t * ref_picture)
558 { 555 {
559 int best[2]={0, 0}; 556 int best[2]={0, 0};
560 int d, dmin; 557 int d, dmin;
561 UINT8 *new_pic, *old_pic; 558 UINT8 *new_pic, *old_pic;
562 const int pic_stride= s->linesize; 559 const int pic_stride= s->linesize;
564 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame 561 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
565 int quant= s->qscale; // qscale of the prev frame 562 int quant= s->qscale; // qscale of the prev frame
566 const int shift= 1+s->quarter_sample; 563 const int shift= 1+s->quarter_sample;
567 564
568 new_pic = s->new_picture[0] + pic_xy; 565 new_pic = s->new_picture[0] + pic_xy;
569 old_pic = s->last_picture[0] + pic_xy; 566 old_pic = ref_picture + pic_xy;
570 567
571 dmin = pix_abs16x16(new_pic, old_pic, pic_stride); 568 dmin = pix_abs16x16(new_pic, old_pic, pic_stride);
572 if(dmin<Z_THRESHOLD){ 569 if(dmin<Z_THRESHOLD){
573 *mx_ptr= 0; 570 *mx_ptr= 0;
574 *my_ptr= 0; 571 *my_ptr= 0;
609 } 606 }
610 607
611 static int epzs_motion_search4(MpegEncContext * s, int block, 608 static int epzs_motion_search4(MpegEncContext * s, int block,
612 int *mx_ptr, int *my_ptr, 609 int *mx_ptr, int *my_ptr,
613 int P[6][2], int pred_x, int pred_y, 610 int P[6][2], int pred_x, int pred_y,
614 int xmin, int ymin, int xmax, int ymax) 611 int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
615 { 612 {
616 int best[2]={0, 0}; 613 int best[2]={0, 0};
617 int d, dmin; 614 int d, dmin;
618 UINT8 *new_pic, *old_pic; 615 UINT8 *new_pic, *old_pic;
619 const int pic_stride= s->linesize; 616 const int pic_stride= s->linesize;
621 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame 618 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 619 int quant= s->qscale; // qscale of the prev frame
623 const int shift= 1+s->quarter_sample; 620 const int shift= 1+s->quarter_sample;
624 621
625 new_pic = s->new_picture[0] + pic_xy; 622 new_pic = s->new_picture[0] + pic_xy;
626 old_pic = s->last_picture[0] + pic_xy; 623 old_pic = ref_picture + pic_xy;
627 624
628 dmin = pix_abs8x8(new_pic, old_pic, pic_stride); 625 dmin = pix_abs8x8(new_pic, old_pic, pic_stride);
629 626
630 /* first line */ 627 /* first line */
631 if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line) && block<2) { 628 if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line) && block<2) {
677 /* The idea would be to make half pel ME after Inter/Intra decision to 674 /* The idea would be to make half pel ME after Inter/Intra decision to
678 save time. */ 675 save time. */
679 static inline void halfpel_motion_search(MpegEncContext * s, 676 static inline void halfpel_motion_search(MpegEncContext * s,
680 int *mx_ptr, int *my_ptr, int dmin, 677 int *mx_ptr, int *my_ptr, int dmin,
681 int xmin, int ymin, int xmax, int ymax, 678 int xmin, int ymin, int xmax, int ymax,
682 int pred_x, int pred_y) 679 int pred_x, int pred_y, uint8_t *ref_picture)
683 { 680 {
684 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame 681 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
685 const int quant= s->qscale; 682 const int quant= s->qscale;
686 int pen_x, pen_y; 683 int pen_x, pen_y;
687 int mx, my, mx1, my1, d, xx, yy, dminh; 684 int mx, my, mx1, my1, d, xx, yy, dminh;
688 UINT8 *pix, *ptr; 685 UINT8 *pix, *ptr;
689 686
690 mx = *mx_ptr; 687 mx = *mx_ptr;
691 my = *my_ptr; 688 my = *my_ptr;
692 ptr = s->last_picture[0] + (my * s->linesize) + mx; 689 ptr = ref_picture + (my * s->linesize) + mx;
693 690
694 xx = 16 * s->mb_x; 691 xx = 16 * s->mb_x;
695 yy = 16 * s->mb_y; 692 yy = 16 * s->mb_y;
696 pix = s->new_picture[0] + (yy * s->linesize) + xx; 693 pix = s->new_picture[0] + (yy * s->linesize) + xx;
697 694
733 } 730 }
734 731
735 static inline void halfpel_motion_search4(MpegEncContext * s, 732 static inline void halfpel_motion_search4(MpegEncContext * s,
736 int *mx_ptr, int *my_ptr, int dmin, 733 int *mx_ptr, int *my_ptr, int dmin,
737 int xmin, int ymin, int xmax, int ymax, 734 int xmin, int ymin, int xmax, int ymax,
738 int pred_x, int pred_y, int block_x, int block_y) 735 int pred_x, int pred_y, int block_x, int block_y,
736 uint8_t *ref_picture)
739 { 737 {
740 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame 738 UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
741 const int quant= s->qscale; 739 const int quant= s->qscale;
742 int pen_x, pen_y; 740 int pen_x, pen_y;
743 int mx, my, mx1, my1, d, xx, yy, dminh; 741 int mx, my, mx1, my1, d, xx, yy, dminh;
747 yy = 8 * block_y; 745 yy = 8 * block_y;
748 pix = s->new_picture[0] + (yy * s->linesize) + xx; 746 pix = s->new_picture[0] + (yy * s->linesize) + xx;
749 747
750 mx = *mx_ptr; 748 mx = *mx_ptr;
751 my = *my_ptr; 749 my = *my_ptr;
752 ptr = s->last_picture[0] + ((yy+my) * s->linesize) + xx + mx; 750 ptr = ref_picture + ((yy+my) * s->linesize) + xx + mx;
753 751
754 dminh = dmin; 752 dminh = dmin;
755 753
756 if (mx > xmin && mx < xmax && 754 if (mx > xmin && mx < xmax &&
757 my > ymin && my < ymax) { 755 my > ymin && my < ymax) {
786 784
787 *mx_ptr = mx; 785 *mx_ptr = mx;
788 *my_ptr = my; 786 *my_ptr = my;
789 } 787 }
790 788
791 static inline void set_mv_tables(MpegEncContext * s, int mx, int my) 789 static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my)
792 { 790 {
793 const int xy= s->mb_x + s->mb_y*s->mb_width; 791 const int xy= s->mb_x + 1 + (s->mb_y + 1)*(s->mb_width + 2);
794 792
795 s->mv_table[0][xy] = mx; 793 s->p_mv_table[xy][0] = mx;
796 s->mv_table[1][xy] = my; 794 s->p_mv_table[xy][1] = my;
797 795
798 /* has allready been set to the 4 MV if 4MV is done */ 796 /* has allready been set to the 4 MV if 4MV is done */
799 if(!(s->flags&CODEC_FLAG_4MV)){ 797 if(!(s->flags&CODEC_FLAG_4MV)){
800 int mot_xy= s->block_index[0]; 798 int mot_xy= s->block_index[0];
801 799
810 s->motion_val[mot_xy+1][0]= mx; 808 s->motion_val[mot_xy+1][0]= mx;
811 s->motion_val[mot_xy+1][1]= my; 809 s->motion_val[mot_xy+1][1]= my;
812 } 810 }
813 } 811 }
814 812
815 #ifndef CONFIG_TEST_MV_ENCODE 813 static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymin, int *xmax, int *ymax, int f_code)
816 814 {
817 void estimate_motion(MpegEncContext * s, 815 *range = 8 * (1 << (f_code - 1));
818 int mb_x, int mb_y) 816 /* XXX: temporary kludge to avoid overflow for msmpeg4 */
817 if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
818 *range *= 2;
819
820 if (s->unrestricted_mv) {
821 *xmin = -16;
822 *ymin = -16;
823 if (s->h263_plus)
824 *range *= 2;
825 if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
826 *xmax = s->mb_width*16;
827 *ymax = s->mb_height*16;
828 }else {
829 /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise
830 (cuz the drawn edge isnt large enough))*/
831 *xmax = s->width;
832 *ymax = s->height;
833 }
834 } else {
835 *xmin = 0;
836 *ymin = 0;
837 *xmax = s->mb_width*16 - 16;
838 *ymax = s->mb_height*16 - 16;
839 }
840 }
841
842 void ff_estimate_p_frame_motion(MpegEncContext * s,
843 int mb_x, int mb_y)
819 { 844 {
820 UINT8 *pix, *ppix; 845 UINT8 *pix, *ppix;
821 int sum, varc, vard, mx, my, range, dmin, xx, yy; 846 int sum, varc, vard, mx, my, range, dmin, xx, yy;
822 int xmin, ymin, xmax, ymax; 847 int xmin, ymin, xmax, ymax;
823 int rel_xmin, rel_ymin, rel_xmax, rel_ymax; 848 int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
824 int pred_x=0, pred_y=0; 849 int pred_x=0, pred_y=0;
825 int P[6][2]; 850 int P[6][2];
826 const int shift= 1+s->quarter_sample; 851 const int shift= 1+s->quarter_sample;
827 int mb_type=0; 852 int mb_type=0;
828 //static int skip=0; 853 uint8_t *ref_picture= s->last_picture[0];
829 range = 8 * (1 << (s->f_code - 1)); 854
830 /* XXX: temporary kludge to avoid overflow for msmpeg4 */ 855 get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code);
831 if (s->out_format == FMT_H263 && !s->h263_msmpeg4) 856
832 range = range * 2;
833
834 if (s->unrestricted_mv) {
835 xmin = -16;
836 ymin = -16;
837 if (s->h263_plus)
838 range *= 2;
839 if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
840 xmax = s->mb_width*16;
841 ymax = s->mb_height*16;
842 }else {
843 /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise
844 (cuz the drawn edge isnt large enough))*/
845 xmax = s->width;
846 ymax = s->height;
847 }
848 } else {
849 xmin = 0;
850 ymin = 0;
851 xmax = s->mb_width*16 - 16;
852 ymax = s->mb_height*16 - 16;
853 }
854 switch(s->me_method) { 857 switch(s->me_method) {
855 case ME_ZERO: 858 case ME_ZERO:
856 default: 859 default:
857 no_motion_search(s, &mx, &my); 860 no_motion_search(s, &mx, &my);
858 dmin = 0; 861 dmin = 0;
859 break; 862 break;
860 case ME_FULL: 863 case ME_FULL:
861 dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax); 864 dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture);
862 break; 865 break;
863 case ME_LOG: 866 case ME_LOG:
864 dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax); 867 dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
865 break; 868 break;
866 case ME_PHODS: 869 case ME_PHODS:
867 dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax); 870 dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
868 break; 871 break;
869 case ME_X1: 872 case ME_X1:
870 case ME_EPZS: 873 case ME_EPZS:
871 { 874 {
872 const int mot_stride = s->block_wrap[0]; 875 const int mot_stride = s->block_wrap[0];
905 }else { /* mpeg1 at least */ 908 }else { /* mpeg1 at least */
906 pred_x= P[1][0]; 909 pred_x= P[1][0];
907 pred_y= P[1][1]; 910 pred_y= P[1][1];
908 } 911 }
909 } 912 }
910 dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax); 913 dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture);
911 914
912 mx+= mb_x*16; 915 mx+= mb_x*16;
913 my+= mb_y*16; 916 my+= mb_y*16;
914 break; 917 break;
915 } 918 }
965 pred_y4= P[1][1]; 968 pred_y4= P[1][1];
966 } 969 }
967 P[5][0]= mx - mb_x*16; 970 P[5][0]= mx - mb_x*16;
968 P[5][1]= my - mb_y*16; 971 P[5][1]= my - mb_y*16;
969 972
970 dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4); 973 dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, ref_picture);
971 974
972 halfpel_motion_search4(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, 975 halfpel_motion_search4(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4,
973 pred_x4, pred_y4, block_x, block_y); 976 pred_x4, pred_y4, block_x, block_y, ref_picture);
974 977
975 s->motion_val[ s->block_index[block] ][0]= mx4; 978 s->motion_val[ s->block_index[block] ][0]= mx4;
976 s->motion_val[ s->block_index[block] ][1]= my4; 979 s->motion_val[ s->block_index[block] ][1]= my4;
977 } 980 }
978 } 981 }
981 xx = mb_x * 16; 984 xx = mb_x * 16;
982 yy = mb_y * 16; 985 yy = mb_y * 16;
983 986
984 pix = s->new_picture[0] + (yy * s->linesize) + xx; 987 pix = s->new_picture[0] + (yy * s->linesize) + xx;
985 /* At this point (mx,my) are full-pell and the absolute displacement */ 988 /* At this point (mx,my) are full-pell and the absolute displacement */
986 ppix = s->last_picture[0] + (my * s->linesize) + mx; 989 ppix = ref_picture + (my * s->linesize) + mx;
987 990
988 sum = pix_sum(pix, s->linesize); 991 sum = pix_sum(pix, s->linesize);
989 #if 0 992 #if 0
990 varc = pix_dev(pix, s->linesize, (sum+128)>>8) + INTER_BIAS; 993 varc = pix_dev(pix, s->linesize, (sum+128)>>8) + INTER_BIAS;
991 vard = pix_abs16x16(pix, ppix, s->linesize); 994 vard = pix_abs16x16(pix, ppix, s->linesize);
1007 if(s->flags&CODEC_FLAG_HQ){ 1010 if(s->flags&CODEC_FLAG_HQ){
1008 if (vard*2 + 200 > varc) 1011 if (vard*2 + 200 > varc)
1009 mb_type|= MB_TYPE_INTRA; 1012 mb_type|= MB_TYPE_INTRA;
1010 if (varc*2 + 200 > vard){ 1013 if (varc*2 + 200 > vard){
1011 mb_type|= MB_TYPE_INTER; 1014 mb_type|= MB_TYPE_INTER;
1012 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); 1015 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y, ref_picture);
1013 }else{ 1016 }else{
1014 mx = mx*2 - mb_x*32; 1017 mx = mx*2 - mb_x*32;
1015 my = my*2 - mb_y*32; 1018 my = my*2 - mb_y*32;
1016 } 1019 }
1017 }else{ 1020 }else{
1018 if (vard <= 64 || vard < varc) { 1021 if (vard <= 64 || vard < varc) {
1019 mb_type|= MB_TYPE_INTER; 1022 mb_type|= MB_TYPE_INTER;
1020 if (s->me_method != ME_ZERO) { 1023 if (s->me_method != ME_ZERO) {
1021 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y); 1024 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y, ref_picture);
1022 } else { 1025 } else {
1023 mx -= 16 * mb_x; 1026 mx -= 16 * mb_x;
1024 my -= 16 * mb_y; 1027 my -= 16 * mb_y;
1025 } 1028 }
1026 #if 0 1029 #if 0
1036 my = 0;//my*2 - 32 * mb_y; 1039 my = 0;//my*2 - 32 * mb_y;
1037 } 1040 }
1038 } 1041 }
1039 1042
1040 s->mb_type[mb_y*s->mb_width + mb_x]= mb_type; 1043 s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
1041 set_mv_tables(s, mx, my); 1044 set_p_mv_tables(s, mx, my);
1042 } 1045 }
1043 1046
1044 #else 1047 void ff_estimate_motion_b(MpegEncContext * s,
1045 1048 int mb_x, int mb_y, int16_t (*mv_table)[2], uint8_t *ref_picture, int f_code)
1046 /* test version which generates valid random vectors */ 1049 {
1047 int estimate_motion(MpegEncContext * s, 1050 UINT8 *pix, *ppix;
1048 int mb_x, int mb_y, 1051 int sum, varc, vard, mx, my, range, dmin, xx, yy;
1049 int *mx_ptr, int *my_ptr) 1052 int xmin, ymin, xmax, ymax;
1050 { 1053 int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
1051 int xx, yy, x1, y1, x2, y2, range; 1054 int pred_x=0, pred_y=0;
1052 1055 int P[6][2];
1053 if ((random() % 10) >= 5) { 1056 const int shift= 1+s->quarter_sample;
1054 range = 8 * (1 << (s->f_code - 1)); 1057 int mb_type=0;
1055 if (s->out_format == FMT_H263 && !s->h263_msmpeg4) 1058 const int mot_stride = s->mb_width + 2;
1056 range = range * 2; 1059 const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1;
1057 1060
1058 xx = 16 * s->mb_x; 1061 get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, f_code);
1059 yy = 16 * s->mb_y; 1062
1060 x1 = xx - range; 1063 switch(s->me_method) {
1061 if (x1 < 0) 1064 case ME_ZERO:
1062 x1 = 0; 1065 default:
1063 x2 = xx + range - 1; 1066 no_motion_search(s, &mx, &my);
1064 if (x2 > (s->width - 16)) 1067 dmin = 0;
1065 x2 = s->width - 16; 1068 break;
1066 y1 = yy - range; 1069 case ME_FULL:
1067 if (y1 < 0) 1070 dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture);
1068 y1 = 0; 1071 break;
1069 y2 = yy + range - 1; 1072 case ME_LOG:
1070 if (y2 > (s->height - 16)) 1073 dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
1071 y2 = s->height - 16; 1074 break;
1072 1075 case ME_PHODS:
1073 *mx_ptr = (random() % (2 * (x2 - x1 + 1))) + 2 * (x1 - xx); 1076 dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
1074 *my_ptr = (random() % (2 * (y2 - y1 + 1))) + 2 * (y1 - yy); 1077 break;
1075 return 0; 1078 case ME_X1:
1076 } else { 1079 case ME_EPZS:
1077 *mx_ptr = 0; 1080 {
1078 *my_ptr = 0; 1081
1079 return 1; 1082 rel_xmin= xmin - mb_x*16;
1080 } 1083 rel_xmax= xmax - mb_x*16;
1081 } 1084 rel_ymin= ymin - mb_y*16;
1082 1085 rel_ymax= ymax - mb_y*16;
1083 #endif 1086
1087 P[0][0] = mv_table[mot_xy ][0];
1088 P[0][1] = mv_table[mot_xy ][1];
1089 P[1][0] = mv_table[mot_xy - 1][0];
1090 P[1][1] = mv_table[mot_xy - 1][1];
1091 if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
1092
1093 /* special case for first line */
1094 if ((mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
1095 P[4][0] = P[1][0];
1096 P[4][1] = P[1][1];
1097 } else {
1098 P[2][0] = mv_table[mot_xy - mot_stride ][0];
1099 P[2][1] = mv_table[mot_xy - mot_stride ][1];
1100 P[3][0] = mv_table[mot_xy - mot_stride + 1 ][0];
1101 P[3][1] = mv_table[mot_xy - mot_stride + 1 ][1];
1102 if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
1103 if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
1104 if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
1105
1106 P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]);
1107 P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]);
1108 }
1109 pred_x= P[1][0];
1110 pred_y= P[1][1];
1111 }
1112 dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture);
1113
1114 mx+= mb_x*16;
1115 my+= mb_y*16;
1116 break;
1117 }
1118
1119 /* intra / predictive decision */
1120 // xx = mb_x * 16;
1121 // yy = mb_y * 16;
1122
1123 // pix = s->new_picture[0] + (yy * s->linesize) + xx;
1124 /* At this point (mx,my) are full-pell and the absolute displacement */
1125 // ppix = ref_picture + (my * s->linesize) + mx;
1126
1127 halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y, ref_picture);
1128
1129 // s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
1130 mv_table[mot_xy][0]= mx;
1131 mv_table[mot_xy][1]= my;
1132 }
1133
1134
1135 int ff_decide_type(MpegEncContext * s,
1136 int mb_x, int mb_y)
1137 {
1138
1139 }
1140
1141 void ff_estimate_b_frame_motion(MpegEncContext * s,
1142 int mb_x, int mb_y)
1143 {
1144 const int mot_stride = s->mb_width + 2;
1145 const int xy = (mb_y + 1)*mot_stride + mb_x + 1;
1146
1147 ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, s->last_picture[0], s->f_code);
1148 ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, s->next_picture[0], s->b_code);
1149 //printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1150 s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
1151 s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
1152 s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
1153 s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
1154
1155 s->mb_type[mb_y*s->mb_width + mb_x]= MB_TYPE_FORWARD; //FIXME
1156 }
1157
1158 /* find best f_code for ME which do unlimited searches */
1159 int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
1160 {
1161 int f_code;
1162
1163 if(s->me_method>=ME_EPZS){
1164 int mv_num[8];
1165 int i, y;
1166 int loose=0;
1167 UINT8 * fcode_tab= s->fcode_tab;
1168
1169 for(i=0; i<8; i++) mv_num[i]=0;
1170
1171 for(y=0; y<s->mb_height; y++){
1172 int x;
1173 int xy= (y+1)* (s->mb_width+2) + 1;
1174 i= y*s->mb_width;
1175 for(x=0; x<s->mb_width; x++){
1176 if(s->mb_type[i] & type){
1177 mv_num[ fcode_tab[mv_table[xy][0] + MAX_MV] ]++;
1178 mv_num[ fcode_tab[mv_table[xy][1] + MAX_MV] ]++;
1179 //printf("%d %d %d\n", s->mv_table[0][i], fcode_tab[s->mv_table[0][i] + MAX_MV], i);
1180 }
1181 i++;
1182 xy++;
1183 }
1184 }
1185
1186 for(i=MAX_FCODE; i>1; i--){
1187 loose+= mv_num[i];
1188 if(loose > s->mb_num/20) break; //FIXME this is pretty ineffective
1189 }
1190 // printf("fcode: %d type: %d\n", i, s->pict_type);
1191 return i;
1192 /* for(i=0; i<=MAX_FCODE; i++){
1193 printf("%d ", mv_num[i]);
1194 }
1195 printf("\n");*/
1196 }else{
1197 return 1;
1198 }
1199 }
1200
1201 void ff_fix_long_p_mvs(MpegEncContext * s)
1202 {
1203 const int f_code= s->f_code;
1204 int y;
1205 UINT8 * fcode_tab= s->fcode_tab;
1206
1207 /* clip / convert to intra 16x16 type MVs */
1208 for(y=0; y<s->mb_height; y++){
1209 int x;
1210 int xy= (y+1)* (s->mb_width+2)+1;
1211 int i= y*s->mb_width;
1212 for(x=0; x<s->mb_width; x++){
1213 if(s->mb_type[i]&MB_TYPE_INTER){
1214 if( fcode_tab[s->p_mv_table[xy][0] + MAX_MV] > f_code
1215 || fcode_tab[s->p_mv_table[xy][0] + MAX_MV] == 0
1216 || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] > f_code
1217 || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] == 0 ){
1218 s->mb_type[i] &= ~MB_TYPE_INTER;
1219 s->mb_type[i] |= MB_TYPE_INTRA;
1220 s->p_mv_table[xy][0] = 0;
1221 s->p_mv_table[xy][1] = 0;
1222 }
1223 }
1224 xy++;
1225 i++;
1226 }
1227 }
1228
1229 if(s->flags&CODEC_FLAG_4MV){
1230 const int wrap= 2+ s->mb_width*2;
1231
1232 /* clip / convert to intra 8x8 type MVs */
1233 for(y=0; y<s->mb_height; y++){
1234 int xy= (y*2 + 1)*wrap + 1;
1235 int i= y*s->mb_width;
1236 int x;
1237
1238 for(x=0; x<s->mb_width; x++){
1239 if(s->mb_type[i]&MB_TYPE_INTER4V){
1240 int block;
1241 for(block=0; block<4; block++){
1242 int off= (block& 1) + (block>>1)*wrap;
1243 int mx= s->motion_val[ xy + off ][0];
1244 int my= s->motion_val[ xy + off ][1];
1245
1246 if( fcode_tab[mx + MAX_MV] > f_code
1247 || fcode_tab[mx + MAX_MV] == 0
1248 || fcode_tab[my + MAX_MV] > f_code
1249 || fcode_tab[my + MAX_MV] == 0 ){
1250 s->mb_type[i] &= ~MB_TYPE_INTER4V;
1251 s->mb_type[i] |= MB_TYPE_INTRA;
1252 }
1253 }
1254 xy+=2;
1255 i++;
1256 }
1257 }
1258 }
1259 }
1260 }
1261
1262 void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type)
1263 {
1264 int y;
1265 UINT8 * fcode_tab= s->fcode_tab;
1266
1267 /* clip / convert to intra 16x16 type MVs */
1268 for(y=0; y<s->mb_height; y++){
1269 int x;
1270 int xy= (y+1)* (s->mb_width+2)+1;
1271 int i= y*s->mb_width;
1272 for(x=0; x<s->mb_width; x++){
1273 if(s->mb_type[i]&type){
1274 if( fcode_tab[mv_table[xy][0] + MAX_MV] > f_code
1275 || fcode_tab[mv_table[xy][0] + MAX_MV] == 0
1276 || fcode_tab[mv_table[xy][1] + MAX_MV] > f_code
1277 || fcode_tab[mv_table[xy][1] + MAX_MV] == 0 ){
1278 s->mb_type[i] &= ~type;
1279 if(s->mb_type[i]==0) s->mb_type[i]= MB_TYPE_FORWARD; //FIXME
1280 mv_table[xy][0] = 0;
1281 mv_table[xy][1] = 0;
1282 //this is certainly bad FIXME
1283 }
1284 }
1285 xy++;
1286 i++;
1287 }
1288 }
1289 }