3 * Copyright (c) 2000,2001 Fabrice Bellard.
4 * Copyright (c) 2002 Michael Niedermayer
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
27 #include "mpegvideo.h"
29 #define SQ(a) ((a)*(a))
30 #define INTER_BIAS 257
35 #define P_TOPRIGHT P[3]
37 #define P_LAST_LEFT P[5]
38 #define P_LAST_RIGHT P[6]
39 #define P_LAST_TOP P[7]
40 #define P_LAST_BOTTOM P[8]
44 static int pix_dev(UINT8
* pix
, int line_size
, int mean
)
49 for (i
= 0; i
< 16; i
++) {
50 for (j
= 0; j
< 16; j
+= 8) {
51 s
+= ABS(pix
[0]-mean
);
52 s
+= ABS(pix
[1]-mean
);
53 s
+= ABS(pix
[2]-mean
);
54 s
+= ABS(pix
[3]-mean
);
55 s
+= ABS(pix
[4]-mean
);
56 s
+= ABS(pix
[5]-mean
);
57 s
+= ABS(pix
[6]-mean
);
58 s
+= ABS(pix
[7]-mean
);
61 pix
+= line_size
- 16;
66 static inline void no_motion_search(MpegEncContext
* s
,
67 int *mx_ptr
, int *my_ptr
)
69 *mx_ptr
= 16 * s
->mb_x
;
70 *my_ptr
= 16 * s
->mb_y
;
73 static int full_motion_search(MpegEncContext
* s
,
74 int *mx_ptr
, int *my_ptr
, int range
,
75 int xmin
, int ymin
, int xmax
, int ymax
, uint8_t *ref_picture
)
77 int x1
, y1
, x2
, y2
, xx
, yy
, x
, y
;
83 x1
= xx
- range
+ 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
95 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
99 for (y
= y1
; y
<= y2
; y
++) {
100 for (x
= x1
; x
<= x2
; x
++) {
101 d
= s
->dsp
.pix_abs16x16(pix
, ref_picture
+ (y
* s
->linesize
) + x
,
105 (abs(x
- xx
) + abs(y
- yy
)) <
106 (abs(mx
- xx
) + abs(my
- yy
)))) {
118 if (*mx_ptr
< -(2 * range
) || *mx_ptr
>= (2 * range
) ||
119 *my_ptr
< -(2 * range
) || *my_ptr
>= (2 * range
)) {
120 fprintf(stderr
, "error %d %d\n", *mx_ptr
, *my_ptr
);
127 static int log_motion_search(MpegEncContext
* s
,
128 int *mx_ptr
, int *my_ptr
, int range
,
129 int xmin
, int ymin
, int xmax
, int ymax
, uint8_t *ref_picture
)
131 int x1
, y1
, x2
, y2
, xx
, yy
, x
, y
;
158 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
164 for (y
= y1
; y
<= y2
; y
+= range
) {
165 for (x
= x1
; x
<= x2
; x
+= range
) {
166 d
= s
->dsp
.pix_abs16x16(pix
, ref_picture
+ (y
* s
->linesize
) + x
, s
->linesize
);
167 if (d
< dmin
|| (d
== dmin
&& (abs(x
- xx
) + abs(y
- yy
)) < (abs(mx
- xx
) + abs(my
- yy
)))) {
193 } while (range
>= 1);
196 fprintf(stderr
, "log - MX: %d\tMY: %d\n", mx
, my
);
203 static int phods_motion_search(MpegEncContext
* s
,
204 int *mx_ptr
, int *my_ptr
, int range
,
205 int xmin
, int ymin
, int xmax
, int ymax
, uint8_t *ref_picture
)
207 int x1
, y1
, x2
, y2
, xx
, yy
, x
, y
, lastx
, d
;
208 int mx
, my
, dminx
, dminy
;
234 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
245 for (x
= x1
; x
<= x2
; x
+= range
) {
246 d
= s
->dsp
.pix_abs16x16(pix
, ref_picture
+ (y
* s
->linesize
) + x
, s
->linesize
);
247 if (d
< dminx
|| (d
== dminx
&& (abs(x
- xx
) + abs(y
- yy
)) < (abs(mx
- xx
) + abs(my
- yy
)))) {
254 for (y
= y1
; y
<= y2
; y
+= range
) {
255 d
= s
->dsp
.pix_abs16x16(pix
, ref_picture
+ (y
* s
->linesize
) + x
, s
->linesize
);
256 if (d
< dminy
|| (d
== dminy
&& (abs(x
- xx
) + abs(y
- yy
)) < (abs(mx
- xx
) + abs(my
- yy
)))) {
282 } while (range
>= 1);
285 fprintf(stderr
, "phods - MX: %d\tMY: %d\n", mx
, my
);
288 /* half pixel search */
295 #define Z_THRESHOLD 256
297 #define CHECK_MV(x,y)\
299 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
300 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
301 if(map[index]!=key){\
302 d = s->dsp.pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
303 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
304 COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
306 score_map[index]= d;\
310 #define CHECK_MV_DIR(x,y,new_dir)\
312 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
313 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
314 if(map[index]!=key){\
315 d = pix_abs(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
316 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
324 score_map[index]= d;\
328 #define CHECK_MV4(x,y)\
330 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
331 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
332 if(map[index]!=key){\
333 d = s->dsp.pix_abs8x8(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
334 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
335 COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
337 score_map[index]= d;\
341 #define check(x,y,S,v)\
342 if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
343 if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
344 if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
345 if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
348 static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
349 UINT8
*new_pic
, UINT8
*old_pic
, int pic_stride
,
350 int pred_x
, int pred_y
, UINT16
*mv_penalty
, int quant
,
351 int xmin
, int ymin
, int xmax
, int ymax
, int shift
,
352 uint32_t *map
, uint16_t *score_map
, int map_generation
,
353 op_pixels_abs_func pix_abs
)
359 const int dir
= next_dir
;
360 const int x
= best
[0];
361 const int y
= best
[1];
365 if(dir
!=2 && x
>xmin
) CHECK_MV_DIR(x
-1, y
, 0)
366 if(dir
!=3 && y
>ymin
) CHECK_MV_DIR(x
, y
-1, 1)
367 if(dir
!=0 && x
<xmax
) CHECK_MV_DIR(x
+1, y
, 2)
368 if(dir
!=1 && y
<ymax
) CHECK_MV_DIR(x
, y
+1, 3)
377 const int x= best[0];
378 const int y= best[1];
379 const int last_min=dmin;
380 if(x>xmin) CHECK_MV(x-1, y )
381 if(y>xmin) CHECK_MV(x , y-1)
382 if(x<xmax) CHECK_MV(x+1, y )
383 if(y<xmax) CHECK_MV(x , y+1)
384 if(x>xmin && y>ymin) CHECK_MV(x-1, y-1)
385 if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
386 if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
387 if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
388 if(x-1>xmin) CHECK_MV(x-2, y )
389 if(y-1>xmin) CHECK_MV(x , y-2)
390 if(x+1<xmax) CHECK_MV(x+2, y )
391 if(y+1<xmax) CHECK_MV(x , y+2)
392 if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
393 if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
394 if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
395 if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)
396 if(dmin==last_min) return dmin;
408 static inline int snake_search(MpegEncContext
* s
, int *best
, int dmin
,
409 UINT8
*new_pic
, UINT8
*old_pic
, int pic_stride
,
410 int pred_x
, int pred_y
, UINT16
*mv_penalty
, int quant
,
411 int xmin
, int ymin
, int xmax
, int ymax
, int shift
,
412 uint32_t *map
, uint16_t *score_map
,int map_generation
,
413 op_pixels_abs_func pix_abs
)
417 static int x_dir
[8]= {1,1,0,-1,-1,-1, 0, 1};
418 static int y_dir
[8]= {0,1,1, 1, 0,-1,-1,-1};
420 int last_d
[2]={dmin
, dmin
};
427 if(256*256*256*64%point==0)
429 printf("%d %d %d\n", good, bad, point);
438 if(x
>=xmin
&& x
<=xmax
&& y
>=ymin
&& y
<=ymax
){
439 const int key
= ((y
)<<ME_MAP_MV_BITS
) + (x
) + map_generation
;
440 const int index
= (((y
)<<ME_MAP_SHIFT
) + (x
))&(ME_MAP_SIZE
-1);
442 d
= pix_abs(new_pic
, old_pic
+ (x
) + (y
)*pic_stride
, pic_stride
);
443 d
+= (mv_penalty
[((x
)<<shift
)-pred_x
] + mv_penalty
[((y
)<<shift
)-pred_y
])*quant
;
449 d
= dmin
+ 10000; //FIXME smarter boundary handling
456 if(last_d
[1] - last_d
[0] > last_d
[0] - d
) c
= -c
;
466 if(fails
>=SNAKE_1
+1) return dmin
;
479 static inline int cross_search(MpegEncContext
* s
, int *best
, int dmin
,
480 UINT8
*new_pic
, UINT8
*old_pic
, int pic_stride
,
481 int pred_x
, int pred_y
, UINT16
*mv_penalty
, int quant
,
482 int xmin
, int ymin
, int xmax
, int ymax
, int shift
,
483 uint32_t *map
, uint16_t *score_map
,int map_generation
,
484 op_pixels_abs_func pix_abs
)
486 static int x_dir
[4]= {-1, 0, 1, 0};
487 static int y_dir
[4]= { 0,-1, 0, 1};
488 int improvement
[2]={100000, 100000};
494 dir
= dirs
[ improvement
[0] > improvement
[1] ? 0 : 1 ];
495 if(improvement
[dir
&1]==-1) return dmin
;
498 const int x
= best
[0] + x_dir
[dir
];
499 const int y
= best
[1] + y_dir
[dir
];
500 const int key
= (y
<<ME_MAP_MV_BITS
) + x
+ map_generation
;
501 const int index
= ((y
<<ME_MAP_SHIFT
) + x
)&(ME_MAP_SIZE
-1);
503 if(x
>=xmin
&& x
<=xmax
&& y
>=ymin
&& y
<=ymax
){
505 d
= pix_abs(new_pic
, old_pic
+ x
+ y
*pic_stride
, pic_stride
);
506 d
+= (mv_penalty
[(x
<<shift
)-pred_x
] + mv_penalty
[(y
<<shift
)-pred_y
])*quant
;
510 improvement
[dir
&1]= dmin
-d
;
511 improvement
[(dir
&1)^1]++;
522 d
= dmin
+ 1000; //FIXME is this a good idea?
524 /* evaluated point was cached or checked and worse */
527 improvement
[dir
&1]= -1;
529 improvement
[dir
&1]= d
-dmin
;
530 last_dir
= dirs
[dir
&1]= dir
^2;
536 static inline int update_map_generation(MpegEncContext
* s
)
538 s
->me_map_generation
+= 1<<(ME_MAP_MV_BITS
*2);
539 if(s
->me_map_generation
==0){
540 s
->me_map_generation
= 1<<(ME_MAP_MV_BITS
*2);
541 memset(s
->me_map
, 0, sizeof(uint32_t)*ME_MAP_SIZE
);
543 return s
->me_map_generation
;
546 static int epzs_motion_search(MpegEncContext
* s
,
547 int *mx_ptr
, int *my_ptr
,
548 int P
[10][2], int pred_x
, int pred_y
,
549 int xmin
, int ymin
, int xmax
, int ymax
, uint8_t * ref_picture
)
553 UINT8
*new_pic
, *old_pic
;
554 const int pic_stride
= s
->linesize
;
555 const int pic_xy
= (s
->mb_y
*pic_stride
+ s
->mb_x
)*16;
556 UINT16
*mv_penalty
= s
->mv_penalty
[s
->f_code
] + MAX_MV
; // f_code of the prev frame
557 int quant
= s
->qscale
; // qscale of the prev frame
558 const int shift
= 1+s
->quarter_sample
;
559 uint32_t *map
= s
->me_map
;
560 uint16_t *score_map
= s
->me_score_map
;
563 new_pic
= s
->new_picture
.data
[0] + pic_xy
;
564 old_pic
= ref_picture
+ pic_xy
;
566 map_generation
= update_map_generation(s
);
568 dmin
= s
->dsp
.pix_abs16x16(new_pic
, old_pic
, pic_stride
);
569 map
[0]= map_generation
;
573 if ((s
->mb_y
== 0 || s
->first_slice_line
)) {
574 CHECK_MV(P_LEFT
[0]>>shift
, P_LEFT
[1]>>shift
)
575 CHECK_MV(P_LAST
[0]>>shift
, P_LAST
[1]>>shift
)
577 if(dmin
<256 && ( P_LEFT
[0] |P_LEFT
[1]
579 |P_TOPRIGHT
[0]|P_TOPRIGHT
[1])==0){
585 CHECK_MV(P_MEDIAN
[0]>>shift
, P_MEDIAN
[1]>>shift
)
587 CHECK_MV(P_LAST
[0] >>shift
, P_LAST
[1] >>shift
)
588 CHECK_MV(P_LEFT
[0] >>shift
, P_LEFT
[1] >>shift
)
589 CHECK_MV(P_TOP
[0] >>shift
, P_TOP
[1] >>shift
)
590 CHECK_MV(P_TOPRIGHT
[0]>>shift
, P_TOPRIGHT
[1]>>shift
)
594 CHECK_MV(P_LAST_RIGHT
[0] >>shift
, P_LAST_RIGHT
[1] >>shift
)
595 CHECK_MV(P_LAST_BOTTOM
[0]>>shift
, P_LAST_BOTTOM
[1]>>shift
)
597 #if 0 //doest only slow things down
602 for(step
=128; step
>0; step
>>=1){
603 const int step2
= step
;
605 for(y
=-step2
+best
[1]; y
<=step2
+best
[1]; y
+=step
){
607 if(y
<ymin
|| y
>ymax
) continue;
609 for(x
=-step2
+best
[0]; x
<=step2
+best
[0]; x
+=step
){
610 if(x
<xmin
|| x
>xmax
) continue;
611 if(x
==best
[0] && y
==best
[1]) continue;
618 //check(best[0],best[1],0, b0)
619 if(s
->me_method
==ME_EPZS
)
620 dmin
= small_diamond_search(s
, best
, dmin
, new_pic
, old_pic
, pic_stride
,
621 pred_x
, pred_y
, mv_penalty
, quant
, xmin
, ymin
, xmax
, ymax
,
622 shift
, map
, score_map
, map_generation
, s
->dsp
.pix_abs16x16
);
624 dmin
= cross_search(s
, best
, dmin
, new_pic
, old_pic
, pic_stride
,
625 pred_x
, pred_y
, mv_penalty
, quant
, xmin
, ymin
, xmax
, ymax
,
626 shift
, map
, score_map
, map_generation
, s
->dsp
.pix_abs16x16
);
627 //check(best[0],best[1],0, b1)
631 // printf("%d %d %d \n", best[0], best[1], dmin);
635 static int epzs_motion_search4(MpegEncContext
* s
, int block
,
636 int *mx_ptr
, int *my_ptr
,
637 int P
[10][2], int pred_x
, int pred_y
,
638 int xmin
, int ymin
, int xmax
, int ymax
, uint8_t *ref_picture
)
642 UINT8
*new_pic
, *old_pic
;
643 const int pic_stride
= s
->linesize
;
644 const int pic_xy
= ((s
->mb_y
*2 + (block
>>1))*pic_stride
+ s
->mb_x
*2 + (block
&1))*8;
645 UINT16
*mv_penalty
= s
->mv_penalty
[s
->f_code
] + MAX_MV
; // f_code of the prev frame
646 int quant
= s
->qscale
; // qscale of the prev frame
647 const int shift
= 1+s
->quarter_sample
;
648 uint32_t *map
= s
->me_map
;
649 uint16_t *score_map
= s
->me_score_map
;
652 new_pic
= s
->new_picture
.data
[0] + pic_xy
;
653 old_pic
= ref_picture
+ pic_xy
;
655 map_generation
= update_map_generation(s
);
658 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
660 if ((s
->mb_y
== 0 || s
->first_slice_line
) && block
<2) {
661 CHECK_MV4(P_LEFT
[0]>>shift
, P_LEFT
[1]>>shift
)
662 CHECK_MV4(P_LAST
[0]>>shift
, P_LAST
[1]>>shift
)
663 CHECK_MV4(P_MV1
[0]>>shift
, P_MV1
[1]>>shift
)
665 CHECK_MV4(P_MV1
[0]>>shift
, P_MV1
[1]>>shift
)
666 //FIXME try some early stop
668 CHECK_MV4(P_MEDIAN
[0]>>shift
, P_MEDIAN
[1]>>shift
)
669 CHECK_MV4(P_LEFT
[0]>>shift
, P_LEFT
[1]>>shift
)
670 CHECK_MV4(P_TOP
[0]>>shift
, P_TOP
[1]>>shift
)
671 CHECK_MV4(P_TOPRIGHT
[0]>>shift
, P_TOPRIGHT
[1]>>shift
)
672 CHECK_MV4(P_LAST
[0]>>shift
, P_LAST
[1]>>shift
)
676 CHECK_MV4(P_LAST_RIGHT
[0]>>shift
, P_LAST_RIGHT
[1]>>shift
)
677 CHECK_MV4(P_LAST_BOTTOM
[0]>>shift
, P_LAST_BOTTOM
[1]>>shift
)
680 if(s
->me_method
==ME_EPZS
)
681 dmin
= small_diamond_search(s
, best
, dmin
, new_pic
, old_pic
, pic_stride
,
682 pred_x
, pred_y
, mv_penalty
, quant
, xmin
, ymin
, xmax
, ymax
,
683 shift
, map
, score_map
, map_generation
, s
->dsp
.pix_abs8x8
);
685 dmin
= cross_search(s
, best
, dmin
, new_pic
, old_pic
, pic_stride
,
686 pred_x
, pred_y
, mv_penalty
, quant
, xmin
, ymin
, xmax
, ymax
,
687 shift
, map
, score_map
, map_generation
, s
->dsp
.pix_abs8x8
);
692 // printf("%d %d %d \n", best[0], best[1], dmin);
696 #define CHECK_HALF_MV(suffix, x, y) \
698 d= pix_abs_ ## suffix(pix, ptr+((x)>>1), s->linesize);\
699 d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\
700 COPY3_IF_LT(dminh, d, dx, x, dy, y)\
704 /* The idea would be to make half pel ME after Inter/Intra decision to
706 static inline int halfpel_motion_search(MpegEncContext
* s
,
707 int *mx_ptr
, int *my_ptr
, int dmin
,
708 int xmin
, int ymin
, int xmax
, int ymax
,
709 int pred_x
, int pred_y
, uint8_t *ref_picture
,
710 op_pixels_abs_func pix_abs_x2
,
711 op_pixels_abs_func pix_abs_y2
, op_pixels_abs_func pix_abs_xy2
, int n
)
713 UINT16
*mv_penalty
= s
->mv_penalty
[s
->f_code
] + MAX_MV
; // f_code of the prev frame
714 const int quant
= s
->qscale
;
715 int mx
, my
, xx
, yy
, dminh
;
724 xx
= 16 * s
->mb_x
+ 8*(n
&1);
725 yy
= 16 * s
->mb_y
+ 8*(n
>>1);
726 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
730 ptr
= ref_picture
+ ((yy
+ my
) * s
->linesize
) + (xx
+ mx
);
734 if (mx
> xmin
&& mx
< xmax
&&
735 my
> ymin
&& my
< ymax
) {
746 CHECK_HALF_MV(xy2
, -1, -1)
747 CHECK_HALF_MV(y2
, 0, -1)
748 CHECK_HALF_MV(xy2
, +1, -1)
751 CHECK_HALF_MV(x2
, -1, 0)
752 CHECK_HALF_MV(x2
, +1, 0)
753 CHECK_HALF_MV(xy2
, -1, +1)
754 CHECK_HALF_MV(y2
, 0, +1)
755 CHECK_HALF_MV(xy2
, +1, +1)
769 static inline int fast_halfpel_motion_search(MpegEncContext
* s
,
770 int *mx_ptr
, int *my_ptr
, int dmin
,
771 int xmin
, int ymin
, int xmax
, int ymax
,
772 int pred_x
, int pred_y
, uint8_t *ref_picture
,
773 op_pixels_abs_func pix_abs_x2
,
774 op_pixels_abs_func pix_abs_y2
, op_pixels_abs_func pix_abs_xy2
, int n
)
776 UINT16
*mv_penalty
= s
->mv_penalty
[s
->f_code
] + MAX_MV
; // f_code of the prev frame
777 uint16_t *score_map
= s
->me_score_map
;
778 const int quant
= s
->qscale
;
779 int mx
, my
, xx
, yy
, dminh
;
790 xx
= 16 * s
->mb_x
+ 8*(n
&1);
791 yy
= 16 * s
->mb_y
+ 8*(n
>>1);
792 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
796 ptr
= ref_picture
+ ((yy
+ my
) * s
->linesize
) + (xx
+ mx
);
800 if (mx
> xmin
&& mx
< xmax
&&
801 my
> ymin
&& my
< ymax
) {
804 const int index
= (my
<<ME_MAP_SHIFT
) + mx
;
805 const int t
= score_map
[(index
-(1<<ME_MAP_SHIFT
))&(ME_MAP_SIZE
-1)];
806 const int l
= score_map
[(index
- 1 )&(ME_MAP_SIZE
-1)];
807 const int r
= score_map
[(index
+ 1 )&(ME_MAP_SIZE
-1)];
808 const int b
= score_map
[(index
+(1<<ME_MAP_SHIFT
))&(ME_MAP_SIZE
-1)];
818 CHECK_HALF_MV(y2
, 0, -1)
820 CHECK_HALF_MV(xy2
, -1, -1)
822 CHECK_HALF_MV(xy2
, +1, -1)
826 CHECK_HALF_MV(xy2
, -1, +1)
828 CHECK_HALF_MV(x2
, -1, 0)
830 CHECK_HALF_MV(xy2
, +1, -1)
832 CHECK_HALF_MV(xy2
, -1, -1)
836 CHECK_HALF_MV(xy2
, +1, +1)
838 CHECK_HALF_MV(x2
, +1, 0)
843 CHECK_HALF_MV(xy2
, -1, -1)
847 CHECK_HALF_MV(xy2
, +1, +1)
849 CHECK_HALF_MV(x2
, -1, 0)
850 CHECK_HALF_MV(xy2
, -1, +1)
853 CHECK_HALF_MV(xy2
, +1, -1)
857 CHECK_HALF_MV(xy2
, -1, +1)
859 CHECK_HALF_MV(x2
, +1, 0)
860 CHECK_HALF_MV(xy2
, +1, +1)
862 CHECK_HALF_MV(y2
, 0, +1)
877 static inline void set_p_mv_tables(MpegEncContext
* s
, int mx
, int my
, int mv4
)
879 const int xy
= s
->mb_x
+ 1 + (s
->mb_y
+ 1)*(s
->mb_width
+ 2);
881 s
->p_mv_table
[xy
][0] = mx
;
882 s
->p_mv_table
[xy
][1] = my
;
884 /* has allready been set to the 4 MV if 4MV is done */
886 int mot_xy
= s
->block_index
[0];
888 s
->motion_val
[mot_xy
][0]= mx
;
889 s
->motion_val
[mot_xy
][1]= my
;
890 s
->motion_val
[mot_xy
+1][0]= mx
;
891 s
->motion_val
[mot_xy
+1][1]= my
;
893 mot_xy
+= s
->block_wrap
[0];
894 s
->motion_val
[mot_xy
][0]= mx
;
895 s
->motion_val
[mot_xy
][1]= my
;
896 s
->motion_val
[mot_xy
+1][0]= mx
;
897 s
->motion_val
[mot_xy
+1][1]= my
;
901 static inline void get_limits(MpegEncContext
*s
, int *range
, int *xmin
, int *ymin
, int *xmax
, int *ymax
, int f_code
)
903 *range
= 8 * (1 << (f_code
- 1));
904 /* XXX: temporary kludge to avoid overflow for msmpeg4 */
905 if (s
->out_format
== FMT_H263
&& !s
->h263_msmpeg4
)
908 if (s
->unrestricted_mv
) {
913 if(s
->avctx
==NULL
|| s
->avctx
->codec
->id
!=CODEC_ID_MPEG4
){
914 *xmax
= s
->mb_width
*16;
915 *ymax
= s
->mb_height
*16;
917 /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise
918 (cuz the drawn edge isnt large enough))*/
925 *xmax
= s
->mb_width
*16 - 16;
926 *ymax
= s
->mb_height
*16 - 16;
930 static inline int mv4_search(MpegEncContext
*s
, int xmin
, int ymin
, int xmax
, int ymax
, int mx
, int my
, int shift
)
934 uint8_t *ref_picture
= s
->last_picture
.data
[0];
937 for(block
=0; block
<4; block
++){
939 int pred_x4
, pred_y4
;
941 static const int off
[4]= {2, 1, 1, -1};
942 const int mot_stride
= s
->block_wrap
[0];
943 const int mot_xy
= s
->block_index
[block
];
944 // const int block_x= (block&1);
945 // const int block_y= (block>>1);
946 #if 1 // this saves us a bit of cliping work and shouldnt affect compression in a negative way
947 const int rel_xmin4
= xmin
;
948 const int rel_xmax4
= xmax
;
949 const int rel_ymin4
= ymin
;
950 const int rel_ymax4
= ymax
;
952 const int rel_xmin4
= xmin
- block_x
*8;
953 const int rel_xmax4
= xmax
- block_x
*8 + 8;
954 const int rel_ymin4
= ymin
- block_y
*8;
955 const int rel_ymax4
= ymax
- block_y
*8 + 8;
957 P_LAST
[0] = s
->motion_val
[mot_xy
][0];
958 P_LAST
[1] = s
->motion_val
[mot_xy
][1];
959 P_LEFT
[0] = s
->motion_val
[mot_xy
- 1][0];
960 P_LEFT
[1] = s
->motion_val
[mot_xy
- 1][1];
961 P_LAST_RIGHT
[0] = s
->motion_val
[mot_xy
+ 1][0];
962 P_LAST_RIGHT
[1] = s
->motion_val
[mot_xy
+ 1][1];
963 P_LAST_BOTTOM
[0]= s
->motion_val
[mot_xy
+ 1*mot_stride
][0];
964 P_LAST_BOTTOM
[1]= s
->motion_val
[mot_xy
+ 1*mot_stride
][1];
966 if(P_LEFT
[0] > (rel_xmax4
<<shift
)) P_LEFT
[0] = (rel_xmax4
<<shift
);
967 if(P_LAST_RIGHT
[0] < (rel_xmin4
<<shift
)) P_LAST_RIGHT
[0] = (rel_xmin4
<<shift
);
968 if(P_LAST_BOTTOM
[1]< (rel_ymin4
<<shift
)) P_LAST_BOTTOM
[1]= (rel_ymin4
<<shift
);
970 /* special case for first line */
971 if ((s
->mb_y
== 0 || s
->first_slice_line
) && block
<2) {
975 P_TOP
[0] = s
->motion_val
[mot_xy
- mot_stride
][0];
976 P_TOP
[1] = s
->motion_val
[mot_xy
- mot_stride
][1];
977 P_TOPRIGHT
[0] = s
->motion_val
[mot_xy
- mot_stride
+ off
[block
]][0];
978 P_TOPRIGHT
[1] = s
->motion_val
[mot_xy
- mot_stride
+ off
[block
]][1];
979 if(P_TOP
[1] > (rel_ymax4
<<shift
)) P_TOP
[1] = (rel_ymax4
<<shift
);
980 if(P_TOPRIGHT
[0] < (rel_xmin4
<<shift
)) P_TOPRIGHT
[0]= (rel_xmin4
<<shift
);
981 if(P_TOPRIGHT
[0] > (rel_xmax4
<<shift
)) P_TOPRIGHT
[0]= (rel_xmax4
<<shift
);
982 if(P_TOPRIGHT
[1] > (rel_ymax4
<<shift
)) P_TOPRIGHT
[1]= (rel_ymax4
<<shift
);
984 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
985 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
987 if(s
->out_format
== FMT_H263
){
988 pred_x4
= P_MEDIAN
[0];
989 pred_y4
= P_MEDIAN
[1];
990 }else { /* mpeg1 at least */
998 dmin4
= epzs_motion_search4(s
, block
, &mx4
, &my4
, P
, pred_x4
, pred_y4
, rel_xmin4
, rel_ymin4
, rel_xmax4
, rel_ymax4
, ref_picture
);
1000 dmin4
= fast_halfpel_motion_search(s
, &mx4
, &my4
, dmin4
, rel_xmin4
, rel_ymin4
, rel_xmax4
, rel_ymax4
,
1001 pred_x4
, pred_y4
, ref_picture
, s
->dsp
.pix_abs8x8_x2
,
1002 s
->dsp
.pix_abs8x8_y2
, s
->dsp
.pix_abs8x8_xy2
, block
);
1004 s
->motion_val
[ s
->block_index
[block
] ][0]= mx4
;
1005 s
->motion_val
[ s
->block_index
[block
] ][1]= my4
;
1011 void ff_estimate_p_frame_motion(MpegEncContext
* s
,
1015 int sum
, varc
, vard
, mx
, my
, range
, dmin
, xx
, yy
;
1016 int xmin
, ymin
, xmax
, ymax
;
1017 int rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
;
1018 int pred_x
=0, pred_y
=0;
1020 const int shift
= 1+s
->quarter_sample
;
1022 uint8_t *ref_picture
= s
->last_picture
.data
[0];
1023 Picture
* const pic
= &s
->current_picture
;
1025 get_limits(s
, &range
, &xmin
, &ymin
, &xmax
, &ymax
, s
->f_code
);
1026 rel_xmin
= xmin
- mb_x
*16;
1027 rel_xmax
= xmax
- mb_x
*16;
1028 rel_ymin
= ymin
- mb_y
*16;
1029 rel_ymax
= ymax
- mb_y
*16;
1032 switch(s
->me_method
) {
1035 no_motion_search(s
, &mx
, &my
);
1041 dmin
= full_motion_search(s
, &mx
, &my
, range
, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1046 dmin
= log_motion_search(s
, &mx
, &my
, range
/ 2, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1051 dmin
= phods_motion_search(s
, &mx
, &my
, range
/ 2, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1058 const int mot_stride
= s
->block_wrap
[0];
1059 const int mot_xy
= s
->block_index
[0];
1061 P_LAST
[0] = s
->motion_val
[mot_xy
][0];
1062 P_LAST
[1] = s
->motion_val
[mot_xy
][1];
1063 P_LEFT
[0] = s
->motion_val
[mot_xy
- 1][0];
1064 P_LEFT
[1] = s
->motion_val
[mot_xy
- 1][1];
1065 P_LAST_RIGHT
[0] = s
->motion_val
[mot_xy
+ 2][0];
1066 P_LAST_RIGHT
[1] = s
->motion_val
[mot_xy
+ 2][1];
1067 P_LAST_BOTTOM
[0]= s
->motion_val
[mot_xy
+ 2*mot_stride
][0];
1068 P_LAST_BOTTOM
[1]= s
->motion_val
[mot_xy
+ 2*mot_stride
][1];
1070 if(P_LEFT
[0] > (rel_xmax
<<shift
)) P_LEFT
[0] = (rel_xmax
<<shift
);
1071 if(P_LAST_RIGHT
[0] < (rel_xmin
<<shift
)) P_LAST_RIGHT
[0] = (rel_xmin
<<shift
);
1072 if(P_LAST_BOTTOM
[1]< (rel_ymin
<<shift
)) P_LAST_BOTTOM
[1]= (rel_ymin
<<shift
);
1074 /* special case for first line */
1075 if ((mb_y
== 0 || s
->first_slice_line
)) {
1079 P_TOP
[0] = s
->motion_val
[mot_xy
- mot_stride
][0];
1080 P_TOP
[1] = s
->motion_val
[mot_xy
- mot_stride
][1];
1081 P_TOPRIGHT
[0] = s
->motion_val
[mot_xy
- mot_stride
+ 2][0];
1082 P_TOPRIGHT
[1] = s
->motion_val
[mot_xy
- mot_stride
+ 2][1];
1083 if(P_TOP
[1] > (rel_ymax
<<shift
)) P_TOP
[1] = (rel_ymax
<<shift
);
1084 if(P_TOPRIGHT
[0] < (rel_xmin
<<shift
)) P_TOPRIGHT
[0]= (rel_xmin
<<shift
);
1085 if(P_TOPRIGHT
[1] > (rel_ymax
<<shift
)) P_TOPRIGHT
[1]= (rel_ymax
<<shift
);
1087 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1088 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1090 if(s
->out_format
== FMT_H263
){
1091 pred_x
= P_MEDIAN
[0];
1092 pred_y
= P_MEDIAN
[1];
1093 }else { /* mpeg1 at least */
1099 dmin
= epzs_motion_search(s
, &mx
, &my
, P
, pred_x
, pred_y
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
, ref_picture
);
1104 /* intra / predictive decision */
1108 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
1109 /* At this point (mx,my) are full-pell and the relative displacement */
1110 ppix
= ref_picture
+ ((yy
+my
) * s
->linesize
) + (xx
+mx
);
1112 sum
= s
->dsp
.pix_sum(pix
, s
->linesize
);
1114 varc
= (s
->dsp
.pix_norm1(pix
, s
->linesize
) - (((unsigned)(sum
*sum
))>>8) + 500 + 128)>>8;
1115 // FIXME: MMX OPTIMIZE
1116 vard
= (s
->dsp
.pix_norm(pix
, ppix
, s
->linesize
)+128)>>8;
1118 //printf("%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout);
1119 pic
->mb_var
[s
->mb_width
* mb_y
+ mb_x
] = varc
;
1120 pic
->mc_mb_var
[s
->mb_width
* mb_y
+ mb_x
] = vard
;
1121 pic
->mb_mean
[s
->mb_width
* mb_y
+ mb_x
] = (sum
+128)>>8;
1122 pic
->mb_var_sum
+= varc
;
1123 pic
->mc_mb_var_sum
+= vard
;
1124 //printf("E%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout);
1127 printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
1128 varc
, s
->avg_mb_var
, sum
, vard
, mx
- xx
, my
- yy
);
1130 if(s
->flags
&CODEC_FLAG_HQ
){
1131 if (vard
<= 64 || vard
< varc
)
1132 s
->scene_change_score
+= ff_sqrt(vard
) - ff_sqrt(varc
);
1134 s
->scene_change_score
+= s
->qscale
;
1136 if (vard
*2 + 200 > varc
)
1137 mb_type
|= MB_TYPE_INTRA
;
1138 if (varc
*2 + 200 > vard
){
1139 mb_type
|= MB_TYPE_INTER
;
1140 if(s
->me_method
>= ME_EPZS
)
1141 fast_halfpel_motion_search(s
, &mx
, &my
, dmin
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1142 pred_x
, pred_y
, ref_picture
, s
->dsp
.pix_abs16x16_x2
,
1143 s
->dsp
.pix_abs16x16_y2
, s
->dsp
.pix_abs16x16_xy2
, 0);
1145 halfpel_motion_search( s
, &mx
, &my
, dmin
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1146 pred_x
, pred_y
, ref_picture
, s
->dsp
.pix_abs16x16_x2
,
1147 s
->dsp
.pix_abs16x16_y2
, s
->dsp
.pix_abs16x16_xy2
, 0);
1152 if((s
->flags
&CODEC_FLAG_4MV
)
1153 && !s
->skip_me
&& varc
>50 && vard
>10){
1154 mv4_search(s
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
, mx
, my
, shift
);
1155 mb_type
|=MB_TYPE_INTER4V
;
1157 set_p_mv_tables(s
, mx
, my
, 0);
1159 set_p_mv_tables(s
, mx
, my
, 1);
1161 if (vard
<= 64 || vard
< varc
) {
1162 s
->scene_change_score
+= ff_sqrt(vard
) - ff_sqrt(varc
);
1163 mb_type
|= MB_TYPE_INTER
;
1164 if (s
->me_method
!= ME_ZERO
) {
1165 if(s
->me_method
>= ME_EPZS
)
1166 dmin
= fast_halfpel_motion_search(s
, &mx
, &my
, dmin
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1167 pred_x
, pred_y
, ref_picture
, s
->dsp
.pix_abs16x16_x2
, s
->dsp
.pix_abs16x16_y2
,
1168 s
->dsp
.pix_abs16x16_xy2
, 0);
1170 dmin
= halfpel_motion_search(s
, &mx
, &my
, dmin
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1171 pred_x
, pred_y
, ref_picture
, s
->dsp
.pix_abs16x16_x2
, s
->dsp
.pix_abs16x16_y2
,
1172 s
->dsp
.pix_abs16x16_xy2
, 0);
1173 if((s
->flags
&CODEC_FLAG_4MV
)
1174 && !s
->skip_me
&& varc
>50 && vard
>10){
1175 int dmin4
= mv4_search(s
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
, mx
, my
, shift
);
1176 if(dmin4
+ 128 <dmin
)
1177 mb_type
= MB_TYPE_INTER4V
;
1179 set_p_mv_tables(s
, mx
, my
, mb_type
!=MB_TYPE_INTER4V
);
1188 fprintf(stderr
,"\nEarly skip: %d vard: %2d varc: %5d dmin: %d",
1189 skip
, vard
, varc
, dmin
);
1193 s
->scene_change_score
+= 20;
1194 mb_type
|= MB_TYPE_INTRA
;
1200 s
->mb_type
[mb_y
*s
->mb_width
+ mb_x
]= mb_type
;
1203 int ff_estimate_motion_b(MpegEncContext
* s
,
1204 int mb_x
, int mb_y
, int16_t (*mv_table
)[2], uint8_t *ref_picture
, int f_code
)
1206 int mx
, my
, range
, dmin
;
1207 int xmin
, ymin
, xmax
, ymax
;
1208 int rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
;
1209 int pred_x
=0, pred_y
=0;
1211 const int shift
= 1+s
->quarter_sample
;
1212 const int mot_stride
= s
->mb_width
+ 2;
1213 const int mot_xy
= (mb_y
+ 1)*mot_stride
+ mb_x
+ 1;
1215 get_limits(s
, &range
, &xmin
, &ymin
, &xmax
, &ymax
, f_code
);
1216 rel_xmin
= xmin
- mb_x
*16;
1217 rel_xmax
= xmax
- mb_x
*16;
1218 rel_ymin
= ymin
- mb_y
*16;
1219 rel_ymax
= ymax
- mb_y
*16;
1221 switch(s
->me_method
) {
1224 no_motion_search(s
, &mx
, &my
);
1230 dmin
= full_motion_search(s
, &mx
, &my
, range
, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1235 dmin
= log_motion_search(s
, &mx
, &my
, range
/ 2, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1240 dmin
= phods_motion_search(s
, &mx
, &my
, range
/ 2, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1248 P_LAST
[0] = mv_table
[mot_xy
][0];
1249 P_LAST
[1] = mv_table
[mot_xy
][1];
1250 P_LEFT
[0] = mv_table
[mot_xy
- 1][0];
1251 P_LEFT
[1] = mv_table
[mot_xy
- 1][1];
1252 P_LAST_RIGHT
[0] = mv_table
[mot_xy
+ 1][0];
1253 P_LAST_RIGHT
[1] = mv_table
[mot_xy
+ 1][1];
1254 P_LAST_BOTTOM
[0] = mv_table
[mot_xy
+ mot_stride
][0];
1255 P_LAST_BOTTOM
[1] = mv_table
[mot_xy
+ mot_stride
][1];
1257 if(P_LEFT
[0] > (rel_xmax
<<shift
)) P_LEFT
[0] = (rel_xmax
<<shift
);
1258 if(P_LAST_RIGHT
[0] < (rel_xmin
<<shift
)) P_LAST_RIGHT
[0] = (rel_xmin
<<shift
);
1259 if(P_LAST_BOTTOM
[1]< (rel_ymin
<<shift
)) P_LAST_BOTTOM
[1]= (rel_ymin
<<shift
);
1261 /* special case for first line */
1262 if ((mb_y
== 0 || s
->first_slice_line
)) {
1264 P_TOP
[0] = mv_table
[mot_xy
- mot_stride
][0];
1265 P_TOP
[1] = mv_table
[mot_xy
- mot_stride
][1];
1266 P_TOPRIGHT
[0] = mv_table
[mot_xy
- mot_stride
+ 1 ][0];
1267 P_TOPRIGHT
[1] = mv_table
[mot_xy
- mot_stride
+ 1 ][1];
1268 if(P_TOP
[1] > (rel_ymax
<<shift
)) P_TOP
[1]= (rel_ymax
<<shift
);
1269 if(P_TOPRIGHT
[0] < (rel_xmin
<<shift
)) P_TOPRIGHT
[0]= (rel_xmin
<<shift
);
1270 if(P_TOPRIGHT
[1] > (rel_ymax
<<shift
)) P_TOPRIGHT
[1]= (rel_ymax
<<shift
);
1272 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1273 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1278 dmin
= epzs_motion_search(s
, &mx
, &my
, P
, pred_x
, pred_y
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
, ref_picture
);
1283 dmin
= fast_halfpel_motion_search(s
, &mx
, &my
, dmin
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1284 pred_x
, pred_y
, ref_picture
, s
->dsp
.pix_abs16x16_x2
, s
->dsp
.pix_abs16x16_y2
,
1285 s
->dsp
.pix_abs16x16_xy2
, 0);
1286 //printf("%d %d %d %d//", s->mb_x, s->mb_y, mx, my);
1287 // s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
1288 mv_table
[mot_xy
][0]= mx
;
1289 mv_table
[mot_xy
][1]= my
;
1294 static inline int check_bidir_mv(MpegEncContext
* s
,
1296 int motion_fx
, int motion_fy
,
1297 int motion_bx
, int motion_by
,
1298 int pred_fx
, int pred_fy
,
1299 int pred_bx
, int pred_by
)
1302 //FIXME direct mode penalty
1303 UINT16
*mv_penalty
= s
->mv_penalty
[s
->f_code
] + MAX_MV
; // f_code of the prev frame
1304 uint8_t *dest_y
= s
->me_scratchpad
;
1310 fbmin
= (mv_penalty
[motion_fx
-pred_fx
] + mv_penalty
[motion_fy
-pred_fy
])*s
->qscale
;
1312 dxy
= ((motion_fy
& 1) << 1) | (motion_fx
& 1);
1313 src_x
= mb_x
* 16 + (motion_fx
>> 1);
1314 src_y
= mb_y
* 16 + (motion_fy
>> 1);
1315 src_x
= clip(src_x
, -16, s
->width
);
1316 if (src_x
== s
->width
)
1318 src_y
= clip(src_y
, -16, s
->height
);
1319 if (src_y
== s
->height
)
1322 ptr
= s
->last_picture
.data
[0] + (src_y
* s
->linesize
) + src_x
;
1323 s
->dsp
.put_pixels_tab
[0][dxy
](dest_y
, ptr
, s
->linesize
, 16);
1325 fbmin
+= (mv_penalty
[motion_bx
-pred_bx
] + mv_penalty
[motion_by
-pred_by
])*s
->qscale
;
1327 dxy
= ((motion_by
& 1) << 1) | (motion_bx
& 1);
1328 src_x
= mb_x
* 16 + (motion_bx
>> 1);
1329 src_y
= mb_y
* 16 + (motion_by
>> 1);
1330 src_x
= clip(src_x
, -16, s
->width
);
1331 if (src_x
== s
->width
)
1333 src_y
= clip(src_y
, -16, s
->height
);
1334 if (src_y
== s
->height
)
1337 ptr
= s
->next_picture
.data
[0] + (src_y
* s
->linesize
) + src_x
;
1338 s
->dsp
.avg_pixels_tab
[0][dxy
](dest_y
, ptr
, s
->linesize
, 16);
1340 fbmin
+= s
->dsp
.pix_abs16x16(s
->new_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
, dest_y
, s
->linesize
);
1344 /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1345 static inline int bidir_refine(MpegEncContext
* s
,
1348 const int mot_stride
= s
->mb_width
+ 2;
1349 const int xy
= (mb_y
+ 1)*mot_stride
+ mb_x
+ 1;
1351 int pred_fx
= s
->b_bidir_forw_mv_table
[xy
-1][0];
1352 int pred_fy
= s
->b_bidir_forw_mv_table
[xy
-1][1];
1353 int pred_bx
= s
->b_bidir_back_mv_table
[xy
-1][0];
1354 int pred_by
= s
->b_bidir_back_mv_table
[xy
-1][1];
1355 int motion_fx
= s
->b_bidir_forw_mv_table
[xy
][0]= s
->b_forw_mv_table
[xy
][0];
1356 int motion_fy
= s
->b_bidir_forw_mv_table
[xy
][1]= s
->b_forw_mv_table
[xy
][1];
1357 int motion_bx
= s
->b_bidir_back_mv_table
[xy
][0]= s
->b_back_mv_table
[xy
][0];
1358 int motion_by
= s
->b_bidir_back_mv_table
[xy
][1]= s
->b_back_mv_table
[xy
][1];
1360 //FIXME do refinement and add flag
1362 fbmin
= check_bidir_mv(s
, mb_x
, mb_y
,
1363 motion_fx
, motion_fy
,
1364 motion_bx
, motion_by
,
1371 static inline int direct_search(MpegEncContext
* s
,
1375 const int mot_stride
= s
->mb_width
+ 2;
1376 const int mot_xy
= (mb_y
+ 1)*mot_stride
+ mb_x
+ 1;
1378 int motion_fx
, motion_fy
, motion_bx
, motion_by
, motion_bx0
, motion_by0
;
1379 int motion_dx
, motion_dy
;
1380 const int motion_px
= s
->p_mv_table
[mot_xy
][0];
1381 const int motion_py
= s
->p_mv_table
[mot_xy
][1];
1382 const int time_pp
= s
->pp_time
;
1383 const int time_pb
= s
->pb_time
;
1384 const int time_bp
= time_pp
- time_pb
;
1386 int mx
, my
, mx2
, my2
;
1387 uint8_t *ref_picture
= s
->me_scratchpad
- (mb_x
- 1 + (mb_y
- 1)*s
->linesize
)*16;
1388 int16_t (*mv_table
)[2]= s
->b_direct_mv_table
;
1389 /* uint16_t *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; */ // f_code of the prev frame
1391 /* thanks to iso-mpeg the rounding is different for the zero vector, so we need to handle that ... */
1392 motion_fx
= (motion_px
*time_pb
)/time_pp
;
1393 motion_fy
= (motion_py
*time_pb
)/time_pp
;
1394 motion_bx0
= (-motion_px
*time_bp
)/time_pp
;
1395 motion_by0
= (-motion_py
*time_bp
)/time_pp
;
1396 motion_dx
= motion_dy
=0;
1397 dmin2
= check_bidir_mv(s
, mb_x
, mb_y
,
1398 motion_fx
, motion_fy
,
1399 motion_bx0
, motion_by0
,
1400 motion_fx
, motion_fy
,
1401 motion_bx0
, motion_by0
) - s
->qscale
;
1403 motion_bx
= motion_fx
- motion_px
;
1404 motion_by
= motion_fy
- motion_py
;
1405 for(by
=-1; by
<2; by
++){
1406 for(bx
=-1; bx
<2; bx
++){
1407 uint8_t *dest_y
= s
->me_scratchpad
+ (by
+1)*s
->linesize
*16 + (bx
+1)*16;
1411 const int width
= s
->width
;
1412 const int height
= s
->height
;
1414 dxy
= ((motion_fy
& 1) << 1) | (motion_fx
& 1);
1415 src_x
= (mb_x
+ bx
) * 16 + (motion_fx
>> 1);
1416 src_y
= (mb_y
+ by
) * 16 + (motion_fy
>> 1);
1417 src_x
= clip(src_x
, -16, width
);
1418 if (src_x
== width
) dxy
&= ~1;
1419 src_y
= clip(src_y
, -16, height
);
1420 if (src_y
== height
) dxy
&= ~2;
1422 ptr
= s
->last_picture
.data
[0] + (src_y
* s
->linesize
) + src_x
;
1423 s
->dsp
.put_pixels_tab
[0][dxy
](dest_y
, ptr
, s
->linesize
, 16);
1425 dxy
= ((motion_by
& 1) << 1) | (motion_bx
& 1);
1426 src_x
= (mb_x
+ bx
) * 16 + (motion_bx
>> 1);
1427 src_y
= (mb_y
+ by
) * 16 + (motion_by
>> 1);
1428 src_x
= clip(src_x
, -16, width
);
1429 if (src_x
== width
) dxy
&= ~1;
1430 src_y
= clip(src_y
, -16, height
);
1431 if (src_y
== height
) dxy
&= ~2;
1433 s
->dsp
.avg_pixels_tab
[0][dxy
](dest_y
, ptr
, s
->linesize
, 16);
1437 P_LAST
[0] = mv_table
[mot_xy
][0];
1438 P_LAST
[1] = mv_table
[mot_xy
][1];
1439 P_LEFT
[0] = mv_table
[mot_xy
- 1][0];
1440 P_LEFT
[1] = mv_table
[mot_xy
- 1][1];
1441 P_LAST_RIGHT
[0] = mv_table
[mot_xy
+ 1][0];
1442 P_LAST_RIGHT
[1] = mv_table
[mot_xy
+ 1][1];
1443 P_LAST_BOTTOM
[0] = mv_table
[mot_xy
+ mot_stride
][0];
1444 P_LAST_BOTTOM
[1] = mv_table
[mot_xy
+ mot_stride
][1];
1446 if(P_LEFT[0] > (rel_xmax<<shift)) P_LEFT[0] = (rel_xmax<<shift);
1447 if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift);
1448 if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift);
1450 /* special case for first line */
1451 if ((mb_y
== 0 || s
->first_slice_line
)) {
1453 P_TOP
[0] = mv_table
[mot_xy
- mot_stride
][0];
1454 P_TOP
[1] = mv_table
[mot_xy
- mot_stride
][1];
1455 P_TOPRIGHT
[0] = mv_table
[mot_xy
- mot_stride
+ 1 ][0];
1456 P_TOPRIGHT
[1] = mv_table
[mot_xy
- mot_stride
+ 1 ][1];
1458 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1459 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1461 dmin
= epzs_motion_search(s
, &mx
, &my
, P
, 0, 0, -16, -16, 15, 15, ref_picture
);
1462 if(mx
==0 && my
==0) dmin
=99999999; // not representable, due to rounding stuff
1471 for(by
=-1; by
<2; by
++){
1472 if(my2
+by
< -32) continue;
1473 for(bx
=-1; bx
<2; bx
++){
1474 if(bx
==0 && by
==0) continue;
1475 if(mx2
+bx
< -32) continue;
1476 dmin2
= check_bidir_mv(s
, mb_x
, mb_y
,
1477 mx2
+bx
+motion_fx
, my2
+by
+motion_fy
,
1478 mx2
+bx
+motion_bx
, my2
+by
+motion_by
,
1479 mx2
+bx
+motion_fx
, my2
+by
+motion_fy
,
1480 motion_bx
, motion_by
) - s
->qscale
;
1493 motion_bx
= motion_bx0
;
1494 motion_by
= motion_by0
;
1497 s
->b_direct_mv_table
[mot_xy
][0]= mx
;
1498 s
->b_direct_mv_table
[mot_xy
][1]= my
;
1499 s
->b_direct_forw_mv_table
[mot_xy
][0]= motion_fx
+ mx
;
1500 s
->b_direct_forw_mv_table
[mot_xy
][1]= motion_fy
+ my
;
1501 s
->b_direct_back_mv_table
[mot_xy
][0]= motion_bx
+ mx
;
1502 s
->b_direct_back_mv_table
[mot_xy
][1]= motion_by
+ my
;
1506 void ff_estimate_b_frame_motion(MpegEncContext
* s
,
1509 const int quant
= s
->qscale
;
1510 int fmin
, bmin
, dmin
, fbmin
;
1513 dmin
= direct_search(s
, mb_x
, mb_y
);
1515 fmin
= ff_estimate_motion_b(s
, mb_x
, mb_y
, s
->b_forw_mv_table
, s
->last_picture
.data
[0], s
->f_code
);
1516 bmin
= ff_estimate_motion_b(s
, mb_x
, mb_y
, s
->b_back_mv_table
, s
->next_picture
.data
[0], s
->b_code
) - quant
;
1517 //printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1519 fbmin
= bidir_refine(s
, mb_x
, mb_y
);
1523 type
=MB_TYPE_DIRECT
;
1527 type
= MB_TYPE_FORWARD
;
1531 type
= MB_TYPE_BACKWARD
;
1535 type
= MB_TYPE_BIDIR
;
1537 score
= ((unsigned)(score
*score
+ 128*256))>>16;
1538 s
->current_picture
.mc_mb_var_sum
+= score
;
1539 s
->current_picture
.mc_mb_var
[mb_y
*s
->mb_width
+ mb_x
] = score
; //FIXME use SSD
1542 if(s
->flags
&CODEC_FLAG_HQ
){
1543 type
= MB_TYPE_FORWARD
| MB_TYPE_BACKWARD
| MB_TYPE_BIDIR
| MB_TYPE_DIRECT
; //FIXME something smarter
1550 if(type==MB_TYPE_DIRECT){
1551 int diff= ABS(s->b_forw_mv_table)
1555 s
->mb_type
[mb_y
*s
->mb_width
+ mb_x
]= type
;
1556 /* if(mb_y==0 && mb_x==0) printf("\n");
1557 if(mb_x==0) printf("\n");
1558 printf("%d", av_log2(type));
1562 /* find best f_code for ME which do unlimited searches */
1563 int ff_get_best_fcode(MpegEncContext
* s
, int16_t (*mv_table
)[2], int type
)
1565 if(s
->me_method
>=ME_EPZS
){
1568 UINT8
* fcode_tab
= s
->fcode_tab
;
1570 int best_score
=-10000000;
1572 for(i
=0; i
<8; i
++) score
[i
]= s
->mb_num
*(8-i
); //FIXME *2 and all other too so its the same but nicer
1574 for(y
=0; y
<s
->mb_height
; y
++){
1576 int xy
= (y
+1)* (s
->mb_width
+2) + 1;
1578 for(x
=0; x
<s
->mb_width
; x
++){
1579 if(s
->mb_type
[i
] & type
){
1580 int fcode
= FFMAX(fcode_tab
[mv_table
[xy
][0] + MAX_MV
],
1581 fcode_tab
[mv_table
[xy
][1] + MAX_MV
]);
1584 for(j
=0; j
<fcode
&& j
<8; j
++){
1585 if(s
->pict_type
==B_TYPE
|| s
->current_picture
.mc_mb_var
[i
] < s
->current_picture
.mb_var
[i
])
1595 if(score
[i
] > best_score
){
1596 best_score
= score
[i
];
1599 // printf("%d %d\n", i, score[i]);
1602 // printf("fcode: %d type: %d\n", i, s->pict_type);
1604 /* for(i=0; i<=MAX_FCODE; i++){
1605 printf("%d ", mv_num[i]);
1613 void ff_fix_long_p_mvs(MpegEncContext
* s
)
1615 const int f_code
= s
->f_code
;
1617 UINT8
* fcode_tab
= s
->fcode_tab
;
1620 /* clip / convert to intra 16x16 type MVs */
1621 for(y
=0; y
<s
->mb_height
; y
++){
1623 int xy
= (y
+1)* (s
->mb_width
+2)+1;
1624 int i
= y
*s
->mb_width
;
1625 for(x
=0; x
<s
->mb_width
; x
++){
1626 if(s
->mb_type
[i
]&MB_TYPE_INTER
){
1627 if( fcode_tab
[s
->p_mv_table
[xy
][0] + MAX_MV
] > f_code
1628 || fcode_tab
[s
->p_mv_table
[xy
][0] + MAX_MV
] == 0
1629 || fcode_tab
[s
->p_mv_table
[xy
][1] + MAX_MV
] > f_code
1630 || fcode_tab
[s
->p_mv_table
[xy
][1] + MAX_MV
] == 0 ){
1631 s
->mb_type
[i
] &= ~MB_TYPE_INTER
;
1632 s
->mb_type
[i
] |= MB_TYPE_INTRA
;
1633 s
->p_mv_table
[xy
][0] = 0;
1634 s
->p_mv_table
[xy
][1] = 0;
1644 //printf("%d no:%d %d//\n", clip, noclip, f_code);
1645 if(s
->flags
&CODEC_FLAG_4MV
){
1646 const int wrap
= 2+ s
->mb_width
*2;
1648 /* clip / convert to intra 8x8 type MVs */
1649 for(y
=0; y
<s
->mb_height
; y
++){
1650 int xy
= (y
*2 + 1)*wrap
+ 1;
1651 int i
= y
*s
->mb_width
;
1654 for(x
=0; x
<s
->mb_width
; x
++){
1655 if(s
->mb_type
[i
]&MB_TYPE_INTER4V
){
1657 for(block
=0; block
<4; block
++){
1658 int off
= (block
& 1) + (block
>>1)*wrap
;
1659 int mx
= s
->motion_val
[ xy
+ off
][0];
1660 int my
= s
->motion_val
[ xy
+ off
][1];
1662 if( fcode_tab
[mx
+ MAX_MV
] > f_code
1663 || fcode_tab
[mx
+ MAX_MV
] == 0
1664 || fcode_tab
[my
+ MAX_MV
] > f_code
1665 || fcode_tab
[my
+ MAX_MV
] == 0 ){
1666 s
->mb_type
[i
] &= ~MB_TYPE_INTER4V
;
1667 s
->mb_type
[i
] |= MB_TYPE_INTRA
;
1678 void ff_fix_long_b_mvs(MpegEncContext
* s
, int16_t (*mv_table
)[2], int f_code
, int type
)
1681 UINT8
* fcode_tab
= s
->fcode_tab
;
1683 /* clip / convert to intra 16x16 type MVs */
1684 for(y
=0; y
<s
->mb_height
; y
++){
1686 int xy
= (y
+1)* (s
->mb_width
+2)+1;
1687 int i
= y
*s
->mb_width
;
1688 for(x
=0; x
<s
->mb_width
; x
++){
1689 if( fcode_tab
[mv_table
[xy
][0] + MAX_MV
] > f_code
1690 || fcode_tab
[mv_table
[xy
][0] + MAX_MV
] == 0){
1691 if(mv_table
[xy
][0]>0) mv_table
[xy
][0]= (16<<f_code
)-1;
1692 else mv_table
[xy
][0]= -(16<<f_code
);
1694 if( fcode_tab
[mv_table
[xy
][1] + MAX_MV
] > f_code
1695 || fcode_tab
[mv_table
[xy
][1] + MAX_MV
] == 0){
1696 if(mv_table
[xy
][1]>0) mv_table
[xy
][1]= (16<<f_code
)-1;
1697 else mv_table
[xy
][1]= -(16<<f_code
);