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