3 * Copyright (c) 2000,2001 Fabrice Bellard.
4 * Copyright (c) 2002-2003 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>
34 #include "mpegvideo.h"
39 #define SQ(a) ((a)*(a))
43 #define P_TOPRIGHT P[3]
47 static inline int sad_hpel_motion_search(MpegEncContext
* s
,
48 int *mx_ptr
, int *my_ptr
, int dmin
,
49 int xmin
, int ymin
, int xmax
, int ymax
,
50 int pred_x
, int pred_y
, Picture
*picture
,
51 int n
, int size
, uint8_t * const mv_penalty
);
53 static inline int update_map_generation(MpegEncContext
* s
)
55 s
->me
.map_generation
+= 1<<(ME_MAP_MV_BITS
*2);
56 if(s
->me
.map_generation
==0){
57 s
->me
.map_generation
= 1<<(ME_MAP_MV_BITS
*2);
58 memset(s
->me
.map
, 0, sizeof(uint32_t)*ME_MAP_SIZE
);
60 return s
->me
.map_generation
;
63 /* shape adaptive search stuff */
64 typedef struct Minima
{
70 static int minima_cmp(const void *a
, const void *b
){
71 const Minima
*da
= (const Minima
*) a
;
72 const Minima
*db
= (const Minima
*) b
;
74 return da
->height
- db
->height
;
78 #define RENAME(a) simple_ ## a
80 #define CMP(d, x, y, size)\
81 d = cmp(s, src_y, (ref_y) + (x) + (y)*(stride), stride);
83 #define CMP_HPEL(d, dx, dy, x, y, size)\
85 const int dxy= (dx) + 2*(dy);\
86 hpel_put[0][dxy](s->me.scratchpad, (ref_y) + (x) + (y)*(stride), stride, (16>>size));\
87 d = cmp_sub(s, s->me.scratchpad, src_y, stride);\
90 #define CMP_QPEL(d, dx, dy, x, y, size)\
92 const int dxy= (dx) + 4*(dy);\
93 qpel_put[0][dxy](s->me.scratchpad, (ref_y) + (x) + (y)*(stride), stride);\
94 d = cmp_sub(s, s->me.scratchpad, src_y, stride);\
97 #include "motion_est_template.c"
105 #define RENAME(a) simple_chroma_ ## a
107 #define CMP(d, x, y, size)\
108 d = cmp(s, src_y, (ref_y) + (x) + (y)*(stride), stride);\
110 int dxy= ((x)&1) + 2*((y)&1);\
111 int c= ((x)>>1) + ((y)>>1)*uvstride;\
113 chroma_hpel_put[0][dxy](s->me.scratchpad, ref_u + c, uvstride, 8);\
114 d += chroma_cmp(s, s->me.scratchpad, src_u, uvstride);\
115 chroma_hpel_put[0][dxy](s->me.scratchpad, ref_v + c, uvstride, 8);\
116 d += chroma_cmp(s, s->me.scratchpad, src_v, uvstride);\
119 #define CMP_HPEL(d, dx, dy, x, y, size)\
121 const int dxy= (dx) + 2*(dy);\
122 hpel_put[0][dxy](s->me.scratchpad, (ref_y) + (x) + (y)*(stride), stride, (16>>size));\
123 d = cmp_sub(s, s->me.scratchpad, src_y, stride);\
125 int cxy= (dxy) | ((x)&1) | (2*((y)&1));\
126 int c= ((x)>>1) + ((y)>>1)*uvstride;\
127 chroma_hpel_put[0][cxy](s->me.scratchpad, ref_u + c, uvstride, 8);\
128 d += chroma_cmp_sub(s, s->me.scratchpad, src_u, uvstride);\
129 chroma_hpel_put[0][cxy](s->me.scratchpad, ref_v + c, uvstride, 8);\
130 d += chroma_cmp_sub(s, s->me.scratchpad, src_v, uvstride);\
134 #define CMP_QPEL(d, dx, dy, x, y, size)\
136 const int dxy= (dx) + 4*(dy);\
137 qpel_put[0][dxy](s->me.scratchpad, (ref_y) + (x) + (y)*(stride), stride);\
138 d = cmp_sub(s, s->me.scratchpad, src_y, stride);\
141 int cx= (4*(x) + (dx))/2;\
142 int cy= (4*(y) + (dy))/2;\
145 cxy= (cx&1) + 2*(cy&1);\
146 c= ((cx)>>1) + ((cy)>>1)*uvstride;\
147 chroma_hpel_put[0][cxy](s->me.scratchpad, ref_u + c, uvstride, 8);\
148 d += chroma_cmp_sub(s, s->me.scratchpad, src_u, uvstride);\
149 chroma_hpel_put[0][cxy](s->me.scratchpad, ref_v + c, uvstride, 8);\
150 d += chroma_cmp_sub(s, s->me.scratchpad, src_v, uvstride);\
154 #include "motion_est_template.c"
161 /* SIMPLE DIRECT HPEL */
162 #define RENAME(a) simple_direct_hpel_ ## a
163 //FIXME precalc divisions stuff
165 #define CMP_DIRECT(d, dx, dy, x, y, size, cmp_func)\
166 if((x) >= xmin && 2*(x) + (dx) <= 2*xmax && (y) >= ymin && 2*(y) + (dy) <= 2*ymax){\
167 const int hx= 2*(x) + (dx);\
168 const int hy= 2*(y) + (dy);\
169 if(s->mv_type==MV_TYPE_8X8){\
172 int fx = s->me.direct_basis_mv[i][0] + hx;\
173 int fy = s->me.direct_basis_mv[i][1] + hy;\
174 int bx = hx ? fx - s->me.co_located_mv[i][0] : s->me.co_located_mv[i][0]*(time_pb - time_pp)/time_pp + (i &1)*16;\
175 int by = hy ? fy - s->me.co_located_mv[i][1] : s->me.co_located_mv[i][1]*(time_pb - time_pp)/time_pp + (i>>1)*16;\
176 int fxy= (fx&1) + 2*(fy&1);\
177 int bxy= (bx&1) + 2*(by&1);\
179 uint8_t *dst= s->me.scratchpad + 8*(i&1) + 8*stride*(i>>1);\
180 hpel_put[1][fxy](dst, (ref_y ) + (fx>>1) + (fy>>1)*(stride), stride, 8);\
181 hpel_avg[1][bxy](dst, (ref2_y) + (bx>>1) + (by>>1)*(stride), stride, 8);\
184 int fx = s->me.direct_basis_mv[0][0] + hx;\
185 int fy = s->me.direct_basis_mv[0][1] + hy;\
186 int bx = hx ? fx - s->me.co_located_mv[0][0] : (s->me.co_located_mv[0][0]*(time_pb - time_pp)/time_pp);\
187 int by = hy ? fy - s->me.co_located_mv[0][1] : (s->me.co_located_mv[0][1]*(time_pb - time_pp)/time_pp);\
188 int fxy= (fx&1) + 2*(fy&1);\
189 int bxy= (bx&1) + 2*(by&1);\
191 assert((fx>>1) + 16*s->mb_x >= -16);\
192 assert((fy>>1) + 16*s->mb_y >= -16);\
193 assert((fx>>1) + 16*s->mb_x <= s->width);\
194 assert((fy>>1) + 16*s->mb_y <= s->height);\
195 assert((bx>>1) + 16*s->mb_x >= -16);\
196 assert((by>>1) + 16*s->mb_y >= -16);\
197 assert((bx>>1) + 16*s->mb_x <= s->width);\
198 assert((by>>1) + 16*s->mb_y <= s->height);\
200 hpel_put[0][fxy](s->me.scratchpad, (ref_y ) + (fx>>1) + (fy>>1)*(stride), stride, 16);\
201 hpel_avg[0][bxy](s->me.scratchpad, (ref2_y) + (bx>>1) + (by>>1)*(stride), stride, 16);\
203 d = cmp_func(s, s->me.scratchpad, src_y, stride);\
208 #define CMP_HPEL(d, dx, dy, x, y, size)\
209 CMP_DIRECT(d, dx, dy, x, y, size, cmp_sub)
211 #define CMP(d, x, y, size)\
212 CMP_DIRECT(d, 0, 0, x, y, size, cmp)
214 #include "motion_est_template.c"
222 /* SIMPLE DIRECT QPEL */
223 #define RENAME(a) simple_direct_qpel_ ## a
225 #define CMP_DIRECT(d, dx, dy, x, y, size, cmp_func)\
226 if((x) >= xmin && 4*(x) + (dx) <= 4*xmax && (y) >= ymin && 4*(y) + (dy) <= 4*ymax){\
227 const int qx= 4*(x) + (dx);\
228 const int qy= 4*(y) + (dy);\
229 if(s->mv_type==MV_TYPE_8X8){\
232 int fx = s->me.direct_basis_mv[i][0] + qx;\
233 int fy = s->me.direct_basis_mv[i][1] + qy;\
234 int bx = qx ? fx - s->me.co_located_mv[i][0] : s->me.co_located_mv[i][0]*(time_pb - time_pp)/time_pp + (i &1)*16;\
235 int by = qy ? fy - s->me.co_located_mv[i][1] : s->me.co_located_mv[i][1]*(time_pb - time_pp)/time_pp + (i>>1)*16;\
236 int fxy= (fx&3) + 4*(fy&3);\
237 int bxy= (bx&3) + 4*(by&3);\
239 uint8_t *dst= s->me.scratchpad + 8*(i&1) + 8*stride*(i>>1);\
240 qpel_put[1][fxy](dst, (ref_y ) + (fx>>2) + (fy>>2)*(stride), stride);\
241 qpel_avg[1][bxy](dst, (ref2_y) + (bx>>2) + (by>>2)*(stride), stride);\
244 int fx = s->me.direct_basis_mv[0][0] + qx;\
245 int fy = s->me.direct_basis_mv[0][1] + qy;\
246 int bx = qx ? fx - s->me.co_located_mv[0][0] : s->me.co_located_mv[0][0]*(time_pb - time_pp)/time_pp;\
247 int by = qy ? fy - s->me.co_located_mv[0][1] : s->me.co_located_mv[0][1]*(time_pb - time_pp)/time_pp;\
248 int fxy= (fx&3) + 4*(fy&3);\
249 int bxy= (bx&3) + 4*(by&3);\
251 qpel_put[1][fxy](s->me.scratchpad , (ref_y ) + (fx>>2) + (fy>>2)*(stride) , stride);\
252 qpel_put[1][fxy](s->me.scratchpad + 8 , (ref_y ) + (fx>>2) + (fy>>2)*(stride) + 8 , stride);\
253 qpel_put[1][fxy](s->me.scratchpad + 8*stride, (ref_y ) + (fx>>2) + (fy>>2)*(stride) + 8*stride, stride);\
254 qpel_put[1][fxy](s->me.scratchpad + 8 + 8*stride, (ref_y ) + (fx>>2) + (fy>>2)*(stride) + 8 + 8*stride, stride);\
255 qpel_avg[1][bxy](s->me.scratchpad , (ref2_y) + (bx>>2) + (by>>2)*(stride) , stride);\
256 qpel_avg[1][bxy](s->me.scratchpad + 8 , (ref2_y) + (bx>>2) + (by>>2)*(stride) + 8 , stride);\
257 qpel_avg[1][bxy](s->me.scratchpad + 8*stride, (ref2_y) + (bx>>2) + (by>>2)*(stride) + 8*stride, stride);\
258 qpel_avg[1][bxy](s->me.scratchpad + 8 + 8*stride, (ref2_y) + (bx>>2) + (by>>2)*(stride) + 8 + 8*stride, stride);\
260 d = cmp_func(s, s->me.scratchpad, src_y, stride);\
265 #define CMP_QPEL(d, dx, dy, x, y, size)\
266 CMP_DIRECT(d, dx, dy, x, y, size, cmp_sub)
268 #define CMP(d, x, y, size)\
269 CMP_DIRECT(d, 0, 0, x, y, size, cmp)
271 #include "motion_est_template.c"
280 static int zero_cmp(void *s
, uint8_t *a
, uint8_t *b
, int stride
){
284 static void set_cmp(MpegEncContext
*s
, me_cmp_func
*cmp
, int type
){
285 DSPContext
* c
= &s
->dsp
;
288 memset(cmp
, 0, sizeof(void*)*11);
296 cmp
[0]= c
->hadamard8_diff
[0];
297 cmp
[1]= c
->hadamard8_diff
[1];
304 cmp
[0]= c
->dct_sad
[0];
305 cmp
[1]= c
->dct_sad
[1];
308 cmp
[0]= c
->quant_psnr
[0];
309 cmp
[1]= c
->quant_psnr
[1];
325 av_log(s
->avctx
, AV_LOG_ERROR
,"internal error in cmp function selection\n");
329 static inline int get_penalty_factor(MpegEncContext
*s
, int type
){
339 return s
->qscale
*s
->qscale
*2;
344 return (s
->qscale
*s
->qscale
*185 + 64)>>7;
348 void ff_init_me(MpegEncContext
*s
){
349 set_cmp(s
, s
->dsp
.me_pre_cmp
, s
->avctx
->me_pre_cmp
);
350 set_cmp(s
, s
->dsp
.me_cmp
, s
->avctx
->me_cmp
);
351 set_cmp(s
, s
->dsp
.me_sub_cmp
, s
->avctx
->me_sub_cmp
);
352 set_cmp(s
, s
->dsp
.mb_cmp
, s
->avctx
->mb_cmp
);
354 if(s
->flags
&CODEC_FLAG_QPEL
){
355 if(s
->avctx
->me_sub_cmp
&FF_CMP_CHROMA
)
356 s
->me
.sub_motion_search
= simple_chroma_qpel_motion_search
;
358 s
->me
.sub_motion_search
= simple_qpel_motion_search
;
360 if(s
->avctx
->me_sub_cmp
&FF_CMP_CHROMA
)
361 s
->me
.sub_motion_search
= simple_chroma_hpel_motion_search
;
362 else if( s
->avctx
->me_sub_cmp
== FF_CMP_SAD
363 && s
->avctx
-> me_cmp
== FF_CMP_SAD
364 && s
->avctx
-> mb_cmp
== FF_CMP_SAD
)
365 s
->me
.sub_motion_search
= sad_hpel_motion_search
;
367 s
->me
.sub_motion_search
= simple_hpel_motion_search
;
370 if(s
->avctx
->me_cmp
&FF_CMP_CHROMA
){
371 s
->me
.motion_search
[0]= simple_chroma_epzs_motion_search
;
372 s
->me
.motion_search
[1]= simple_chroma_epzs_motion_search4
;
374 s
->me
.motion_search
[0]= simple_epzs_motion_search
;
375 s
->me
.motion_search
[1]= simple_epzs_motion_search4
;
378 if(s
->avctx
->me_pre_cmp
&FF_CMP_CHROMA
){
379 s
->me
.pre_motion_search
= simple_chroma_epzs_motion_search
;
381 s
->me
.pre_motion_search
= simple_epzs_motion_search
;
384 if(s
->flags
&CODEC_FLAG_QPEL
){
385 if(s
->avctx
->mb_cmp
&FF_CMP_CHROMA
)
386 s
->me
.get_mb_score
= simple_chroma_qpel_get_mb_score
;
388 s
->me
.get_mb_score
= simple_qpel_get_mb_score
;
390 if(s
->avctx
->mb_cmp
&FF_CMP_CHROMA
)
391 s
->me
.get_mb_score
= simple_chroma_hpel_get_mb_score
;
393 s
->me
.get_mb_score
= simple_hpel_get_mb_score
;
398 static int pix_dev(uint8_t * pix
, int line_size
, int mean
)
403 for (i
= 0; i
< 16; i
++) {
404 for (j
= 0; j
< 16; j
+= 8) {
405 s
+= ABS(pix
[0]-mean
);
406 s
+= ABS(pix
[1]-mean
);
407 s
+= ABS(pix
[2]-mean
);
408 s
+= ABS(pix
[3]-mean
);
409 s
+= ABS(pix
[4]-mean
);
410 s
+= ABS(pix
[5]-mean
);
411 s
+= ABS(pix
[6]-mean
);
412 s
+= ABS(pix
[7]-mean
);
415 pix
+= line_size
- 16;
421 static inline void no_motion_search(MpegEncContext
* s
,
422 int *mx_ptr
, int *my_ptr
)
424 *mx_ptr
= 16 * s
->mb_x
;
425 *my_ptr
= 16 * s
->mb_y
;
428 static int full_motion_search(MpegEncContext
* s
,
429 int *mx_ptr
, int *my_ptr
, int range
,
430 int xmin
, int ymin
, int xmax
, int ymax
, uint8_t *ref_picture
)
432 int x1
, y1
, x2
, y2
, xx
, yy
, x
, y
;
438 x1
= xx
- range
+ 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
450 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
454 for (y
= y1
; y
<= y2
; y
++) {
455 for (x
= x1
; x
<= x2
; x
++) {
456 d
= s
->dsp
.pix_abs16x16(pix
, ref_picture
+ (y
* s
->linesize
) + x
,
460 (abs(x
- xx
) + abs(y
- yy
)) <
461 (abs(mx
- xx
) + abs(my
- yy
)))) {
473 if (*mx_ptr
< -(2 * range
) || *mx_ptr
>= (2 * range
) ||
474 *my_ptr
< -(2 * range
) || *my_ptr
>= (2 * range
)) {
475 fprintf(stderr
, "error %d %d\n", *mx_ptr
, *my_ptr
);
482 static int log_motion_search(MpegEncContext
* s
,
483 int *mx_ptr
, int *my_ptr
, int range
,
484 int xmin
, int ymin
, int xmax
, int ymax
, uint8_t *ref_picture
)
486 int x1
, y1
, x2
, y2
, xx
, yy
, x
, y
;
513 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
519 for (y
= y1
; y
<= y2
; y
+= range
) {
520 for (x
= x1
; x
<= x2
; x
+= range
) {
521 d
= s
->dsp
.pix_abs16x16(pix
, ref_picture
+ (y
* s
->linesize
) + x
, s
->linesize
);
522 if (d
< dmin
|| (d
== dmin
&& (abs(x
- xx
) + abs(y
- yy
)) < (abs(mx
- xx
) + abs(my
- yy
)))) {
548 } while (range
>= 1);
551 fprintf(stderr
, "log - MX: %d\tMY: %d\n", mx
, my
);
558 static int phods_motion_search(MpegEncContext
* s
,
559 int *mx_ptr
, int *my_ptr
, int range
,
560 int xmin
, int ymin
, int xmax
, int ymax
, uint8_t *ref_picture
)
562 int x1
, y1
, x2
, y2
, xx
, yy
, x
, y
, lastx
, d
;
563 int mx
, my
, dminx
, dminy
;
589 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
600 for (x
= x1
; x
<= x2
; x
+= range
) {
601 d
= s
->dsp
.pix_abs16x16(pix
, ref_picture
+ (y
* s
->linesize
) + x
, s
->linesize
);
602 if (d
< dminx
|| (d
== dminx
&& (abs(x
- xx
) + abs(y
- yy
)) < (abs(mx
- xx
) + abs(my
- yy
)))) {
609 for (y
= y1
; y
<= y2
; y
+= range
) {
610 d
= s
->dsp
.pix_abs16x16(pix
, ref_picture
+ (y
* s
->linesize
) + x
, s
->linesize
);
611 if (d
< dminy
|| (d
== dminy
&& (abs(x
- xx
) + abs(y
- yy
)) < (abs(mx
- xx
) + abs(my
- yy
)))) {
637 } while (range
>= 1);
640 fprintf(stderr
, "phods - MX: %d\tMY: %d\n", mx
, my
);
643 /* half pixel search */
650 #define Z_THRESHOLD 256
652 #define CHECK_SAD_HALF_MV(suffix, x, y) \
654 d= pix_abs_ ## suffix(pix, ptr+((x)>>1), s->linesize);\
655 d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\
656 COPY3_IF_LT(dminh, d, dx, x, dy, y)\
659 static inline int sad_hpel_motion_search(MpegEncContext
* s
,
660 int *mx_ptr
, int *my_ptr
, int dmin
,
661 int xmin
, int ymin
, int xmax
, int ymax
,
662 int pred_x
, int pred_y
, Picture
*picture
,
663 int n
, int size
, uint8_t * const mv_penalty
)
665 uint8_t *ref_picture
= picture
->data
[0];
666 uint32_t *score_map
= s
->me
.score_map
;
667 const int penalty_factor
= s
->me
.sub_penalty_factor
;
668 int mx
, my
, xx
, yy
, dminh
;
670 op_pixels_abs_func pix_abs_x2
;
671 op_pixels_abs_func pix_abs_y2
;
672 op_pixels_abs_func pix_abs_xy2
;
675 pix_abs_x2
= s
->dsp
.pix_abs16x16_x2
;
676 pix_abs_y2
= s
->dsp
.pix_abs16x16_y2
;
677 pix_abs_xy2
= s
->dsp
.pix_abs16x16_xy2
;
679 pix_abs_x2
= s
->dsp
.pix_abs8x8_x2
;
680 pix_abs_y2
= s
->dsp
.pix_abs8x8_y2
;
681 pix_abs_xy2
= s
->dsp
.pix_abs8x8_xy2
;
692 xx
= 16 * s
->mb_x
+ 8*(n
&1);
693 yy
= 16 * s
->mb_y
+ 8*(n
>>1);
694 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
698 ptr
= ref_picture
+ ((yy
+ my
) * s
->linesize
) + (xx
+ mx
);
702 if (mx
> xmin
&& mx
< xmax
&&
703 my
> ymin
&& my
< ymax
) {
706 const int index
= (my
<<ME_MAP_SHIFT
) + mx
;
707 const int t
= score_map
[(index
-(1<<ME_MAP_SHIFT
))&(ME_MAP_SIZE
-1)];
708 const int l
= score_map
[(index
- 1 )&(ME_MAP_SIZE
-1)];
709 const int r
= score_map
[(index
+ 1 )&(ME_MAP_SIZE
-1)];
710 const int b
= score_map
[(index
+(1<<ME_MAP_SHIFT
))&(ME_MAP_SIZE
-1)];
720 CHECK_SAD_HALF_MV(y2
, 0, -1)
722 CHECK_SAD_HALF_MV(xy2
, -1, -1)
724 CHECK_SAD_HALF_MV(xy2
, +1, -1)
728 CHECK_SAD_HALF_MV(xy2
, -1, +1)
730 CHECK_SAD_HALF_MV(x2
, -1, 0)
732 CHECK_SAD_HALF_MV(xy2
, +1, -1)
734 CHECK_SAD_HALF_MV(xy2
, -1, -1)
738 CHECK_SAD_HALF_MV(xy2
, +1, +1)
740 CHECK_SAD_HALF_MV(x2
, +1, 0)
745 CHECK_SAD_HALF_MV(xy2
, -1, -1)
749 CHECK_SAD_HALF_MV(xy2
, +1, +1)
751 CHECK_SAD_HALF_MV(x2
, -1, 0)
752 CHECK_SAD_HALF_MV(xy2
, -1, +1)
755 CHECK_SAD_HALF_MV(xy2
, +1, -1)
759 CHECK_SAD_HALF_MV(xy2
, -1, +1)
761 CHECK_SAD_HALF_MV(x2
, +1, 0)
762 CHECK_SAD_HALF_MV(xy2
, +1, +1)
764 CHECK_SAD_HALF_MV(y2
, 0, +1)
779 static inline void set_p_mv_tables(MpegEncContext
* s
, int mx
, int my
, int mv4
)
781 const int xy
= s
->mb_x
+ s
->mb_y
*s
->mb_stride
;
783 s
->p_mv_table
[xy
][0] = mx
;
784 s
->p_mv_table
[xy
][1] = my
;
786 /* has allready been set to the 4 MV if 4MV is done */
788 int mot_xy
= s
->block_index
[0];
790 s
->current_picture
.motion_val
[0][mot_xy
][0]= mx
;
791 s
->current_picture
.motion_val
[0][mot_xy
][1]= my
;
792 s
->current_picture
.motion_val
[0][mot_xy
+1][0]= mx
;
793 s
->current_picture
.motion_val
[0][mot_xy
+1][1]= my
;
795 mot_xy
+= s
->block_wrap
[0];
796 s
->current_picture
.motion_val
[0][mot_xy
][0]= mx
;
797 s
->current_picture
.motion_val
[0][mot_xy
][1]= my
;
798 s
->current_picture
.motion_val
[0][mot_xy
+1][0]= mx
;
799 s
->current_picture
.motion_val
[0][mot_xy
+1][1]= my
;
804 * get fullpel ME search limits.
805 * @param range the approximate search range for the old ME code, unused for EPZS and newer
807 static inline void get_limits(MpegEncContext
*s
, int *range
, int *xmin
, int *ymin
, int *xmax
, int *ymax
)
809 if(s
->avctx
->me_range
) *range
= s
->avctx
->me_range
>> 1;
812 if (s
->unrestricted_mv
) {
815 *xmax
= s
->mb_width
*16;
816 *ymax
= s
->mb_height
*16;
820 *xmax
= s
->mb_width
*16 - 16;
821 *ymax
= s
->mb_height
*16 - 16;
824 //FIXME try to limit x/y min/max if me_range is set
827 static inline int h263_mv4_search(MpegEncContext
*s
, int xmin
, int ymin
, int xmax
, int ymax
, int mx
, int my
, int shift
)
831 int dmin_sum
=0, mx4_sum
=0, my4_sum
=0;
832 uint8_t * const mv_penalty
= s
->me
.mv_penalty
[s
->f_code
] + MAX_MV
;
835 for(block
=0; block
<4; block
++){
837 int pred_x4
, pred_y4
;
839 static const int off
[4]= {2, 1, 1, -1};
840 const int mot_stride
= s
->block_wrap
[0];
841 const int mot_xy
= s
->block_index
[block
];
842 // const int block_x= (block&1);
843 // const int block_y= (block>>1);
844 #if 1 // this saves us a bit of cliping work and shouldnt affect compression in a negative way
845 const int rel_xmin4
= xmin
;
846 const int rel_xmax4
= xmax
;
847 const int rel_ymin4
= ymin
;
848 const int rel_ymax4
= ymax
;
850 const int rel_xmin4
= xmin
- block_x
*8;
851 const int rel_xmax4
= xmax
- block_x
*8 + 8;
852 const int rel_ymin4
= ymin
- block_y
*8;
853 const int rel_ymax4
= ymax
- block_y
*8 + 8;
855 P_LEFT
[0] = s
->current_picture
.motion_val
[0][mot_xy
- 1][0];
856 P_LEFT
[1] = s
->current_picture
.motion_val
[0][mot_xy
- 1][1];
858 if(P_LEFT
[0] > (rel_xmax4
<<shift
)) P_LEFT
[0] = (rel_xmax4
<<shift
);
860 /* special case for first line */
861 if (s
->mb_y
== 0 && block
<2) {
865 P_TOP
[0] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
][0];
866 P_TOP
[1] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
][1];
867 P_TOPRIGHT
[0] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
+ off
[block
]][0];
868 P_TOPRIGHT
[1] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
+ off
[block
]][1];
869 if(P_TOP
[1] > (rel_ymax4
<<shift
)) P_TOP
[1] = (rel_ymax4
<<shift
);
870 if(P_TOPRIGHT
[0] < (rel_xmin4
<<shift
)) P_TOPRIGHT
[0]= (rel_xmin4
<<shift
);
871 if(P_TOPRIGHT
[0] > (rel_xmax4
<<shift
)) P_TOPRIGHT
[0]= (rel_xmax4
<<shift
);
872 if(P_TOPRIGHT
[1] > (rel_ymax4
<<shift
)) P_TOPRIGHT
[1]= (rel_ymax4
<<shift
);
874 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
875 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
877 // if(s->out_format == FMT_H263){
878 pred_x4
= P_MEDIAN
[0];
879 pred_y4
= P_MEDIAN
[1];
881 }else { /* mpeg1 at least */
890 dmin4
= s
->me
.motion_search
[1](s
, block
, &mx4
, &my4
, P
, pred_x4
, pred_y4
, rel_xmin4
, rel_ymin4
, rel_xmax4
, rel_ymax4
,
891 &s
->last_picture
, s
->p_mv_table
, (1<<16)>>shift
, mv_penalty
);
893 dmin4
= s
->me
.sub_motion_search(s
, &mx4
, &my4
, dmin4
, rel_xmin4
, rel_ymin4
, rel_xmax4
, rel_ymax4
,
894 pred_x4
, pred_y4
, &s
->last_picture
, block
, 1, mv_penalty
);
896 if(s
->dsp
.me_sub_cmp
[0] != s
->dsp
.mb_cmp
[0]){
898 const int offset
= ((block
&1) + (block
>>1)*s
->linesize
)*8;
899 uint8_t *dest_y
= s
->me
.scratchpad
+ offset
;
901 if(s
->quarter_sample
){
902 uint8_t *ref
= s
->last_picture
.data
[0] + (s
->mb_x
*16 + (mx4
>>2)) + (s
->mb_y
*16 + (my4
>>2))*s
->linesize
+ offset
;
903 dxy
= ((my4
& 3) << 2) | (mx4
& 3);
906 s
->dsp
.put_no_rnd_qpel_pixels_tab
[1][dxy
](dest_y
, ref
, s
->linesize
);
908 s
->dsp
.put_qpel_pixels_tab
[1][dxy
](dest_y
, ref
, s
->linesize
);
910 uint8_t *ref
= s
->last_picture
.data
[0] + (s
->mb_x
*16 + (mx4
>>1)) + (s
->mb_y
*16 + (my4
>>1))*s
->linesize
+ offset
;
911 dxy
= ((my4
& 1) << 1) | (mx4
& 1);
914 s
->dsp
.put_no_rnd_pixels_tab
[1][dxy
](dest_y
, ref
, s
->linesize
, 8);
916 s
->dsp
.put_pixels_tab
[1][dxy
](dest_y
, ref
, s
->linesize
, 8);
918 dmin_sum
+= (mv_penalty
[mx4
-pred_x4
] + mv_penalty
[my4
-pred_y4
])*s
->me
.mb_penalty_factor
;
922 if(s
->quarter_sample
){
930 s
->current_picture
.motion_val
[0][ s
->block_index
[block
] ][0]= mx4
;
931 s
->current_picture
.motion_val
[0][ s
->block_index
[block
] ][1]= my4
;
933 if(mx4
!= mx
|| my4
!= my
) same
=0;
939 if(s
->dsp
.me_sub_cmp
[0] != s
->dsp
.mb_cmp
[0]){
940 dmin_sum
+= s
->dsp
.mb_cmp
[0](s
, s
->new_picture
.data
[0] + s
->mb_x
*16 + s
->mb_y
*16*s
->linesize
, s
->me
.scratchpad
, s
->linesize
);
943 if(s
->avctx
->mb_cmp
&FF_CMP_CHROMA
){
948 mx
= ff_h263_round_chroma(mx4_sum
);
949 my
= ff_h263_round_chroma(my4_sum
);
950 dxy
= ((my
& 1) << 1) | (mx
& 1);
952 offset
= (s
->mb_x
*8 + (mx
>>1)) + (s
->mb_y
*8 + (my
>>1))*s
->uvlinesize
;
955 s
->dsp
.put_no_rnd_pixels_tab
[1][dxy
](s
->me
.scratchpad
, s
->last_picture
.data
[1] + offset
, s
->uvlinesize
, 8);
956 s
->dsp
.put_no_rnd_pixels_tab
[1][dxy
](s
->me
.scratchpad
+8 , s
->last_picture
.data
[2] + offset
, s
->uvlinesize
, 8);
958 s
->dsp
.put_pixels_tab
[1][dxy
](s
->me
.scratchpad
, s
->last_picture
.data
[1] + offset
, s
->uvlinesize
, 8);
959 s
->dsp
.put_pixels_tab
[1][dxy
](s
->me
.scratchpad
+8 , s
->last_picture
.data
[2] + offset
, s
->uvlinesize
, 8);
962 dmin_sum
+= s
->dsp
.mb_cmp
[1](s
, s
->new_picture
.data
[1] + s
->mb_x
*8 + s
->mb_y
*8*s
->uvlinesize
, s
->me
.scratchpad
, s
->uvlinesize
);
963 dmin_sum
+= s
->dsp
.mb_cmp
[1](s
, s
->new_picture
.data
[2] + s
->mb_x
*8 + s
->mb_y
*8*s
->uvlinesize
, s
->me
.scratchpad
+8, s
->uvlinesize
);
966 switch(s
->avctx
->mb_cmp
&0xFF){
968 return dmin_sum+ 32*s->qscale*s->qscale;*/
972 return dmin_sum
+ 11*s
->me
.mb_penalty_factor
;
976 void ff_estimate_p_frame_motion(MpegEncContext
* s
,
980 int sum
, varc
, vard
, mx
, my
, range
, dmin
, xx
, yy
;
981 int xmin
, ymin
, xmax
, ymax
;
982 int rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
;
983 int pred_x
=0, pred_y
=0;
985 const int shift
= 1+s
->quarter_sample
;
987 uint8_t *ref_picture
= s
->last_picture
.data
[0];
988 Picture
* const pic
= &s
->current_picture
;
989 uint8_t * const mv_penalty
= s
->me
.mv_penalty
[s
->f_code
] + MAX_MV
;
991 assert(s
->quarter_sample
==0 || s
->quarter_sample
==1);
993 s
->me
.penalty_factor
= get_penalty_factor(s
, s
->avctx
->me_cmp
);
994 s
->me
.sub_penalty_factor
= get_penalty_factor(s
, s
->avctx
->me_sub_cmp
);
995 s
->me
.mb_penalty_factor
= get_penalty_factor(s
, s
->avctx
->mb_cmp
);
997 get_limits(s
, &range
, &xmin
, &ymin
, &xmax
, &ymax
);
998 rel_xmin
= xmin
- mb_x
*16;
999 rel_xmax
= xmax
- mb_x
*16;
1000 rel_ymin
= ymin
- mb_y
*16;
1001 rel_ymax
= ymax
- mb_y
*16;
1004 switch(s
->me_method
) {
1007 no_motion_search(s
, &mx
, &my
);
1013 dmin
= full_motion_search(s
, &mx
, &my
, range
, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1018 dmin
= log_motion_search(s
, &mx
, &my
, range
/ 2, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1023 dmin
= phods_motion_search(s
, &mx
, &my
, range
/ 2, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1030 const int mot_stride
= s
->block_wrap
[0];
1031 const int mot_xy
= s
->block_index
[0];
1033 P_LEFT
[0] = s
->current_picture
.motion_val
[0][mot_xy
- 1][0];
1034 P_LEFT
[1] = s
->current_picture
.motion_val
[0][mot_xy
- 1][1];
1036 if(P_LEFT
[0] > (rel_xmax
<<shift
)) P_LEFT
[0] = (rel_xmax
<<shift
);
1039 P_TOP
[0] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
][0];
1040 P_TOP
[1] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
][1];
1041 P_TOPRIGHT
[0] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
+ 2][0];
1042 P_TOPRIGHT
[1] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
+ 2][1];
1043 if(P_TOP
[1] > (rel_ymax
<<shift
)) P_TOP
[1] = (rel_ymax
<<shift
);
1044 if(P_TOPRIGHT
[0] < (rel_xmin
<<shift
)) P_TOPRIGHT
[0]= (rel_xmin
<<shift
);
1045 if(P_TOPRIGHT
[1] > (rel_ymax
<<shift
)) P_TOPRIGHT
[1]= (rel_ymax
<<shift
);
1047 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1048 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1050 if(s
->out_format
== FMT_H263
){
1051 pred_x
= P_MEDIAN
[0];
1052 pred_y
= P_MEDIAN
[1];
1053 }else { /* mpeg1 at least */
1063 dmin
= s
->me
.motion_search
[0](s
, 0, &mx
, &my
, P
, pred_x
, pred_y
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1064 &s
->last_picture
, s
->p_mv_table
, (1<<16)>>shift
, mv_penalty
);
1069 /* intra / predictive decision */
1073 pix
= s
->new_picture
.data
[0] + (yy
* s
->linesize
) + xx
;
1074 /* At this point (mx,my) are full-pell and the relative displacement */
1075 ppix
= ref_picture
+ ((yy
+my
) * s
->linesize
) + (xx
+mx
);
1077 sum
= s
->dsp
.pix_sum(pix
, s
->linesize
);
1079 varc
= (s
->dsp
.pix_norm1(pix
, s
->linesize
) - (((unsigned)(sum
*sum
))>>8) + 500 + 128)>>8;
1080 vard
= (s
->dsp
.sse
[0](NULL
, pix
, ppix
, s
->linesize
)+128)>>8;
1082 //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);
1083 pic
->mb_var
[s
->mb_stride
* mb_y
+ mb_x
] = varc
;
1084 pic
->mc_mb_var
[s
->mb_stride
* mb_y
+ mb_x
] = vard
;
1085 pic
->mb_mean
[s
->mb_stride
* mb_y
+ mb_x
] = (sum
+128)>>8;
1086 // pic->mb_cmp_score[s->mb_stride * mb_y + mb_x] = dmin;
1087 pic
->mb_var_sum
+= varc
;
1088 pic
->mc_mb_var_sum
+= vard
;
1089 //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);
1092 printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
1093 varc
, s
->avg_mb_var
, sum
, vard
, mx
- xx
, my
- yy
);
1095 if(s
->avctx
->mb_decision
> FF_MB_DECISION_SIMPLE
){
1096 if (vard
<= 64 || vard
< varc
)
1097 s
->scene_change_score
+= ff_sqrt(vard
) - ff_sqrt(varc
);
1099 s
->scene_change_score
+= s
->qscale
;
1101 if (vard
*2 + 200 > varc
)
1102 mb_type
|= MB_TYPE_INTRA
;
1103 if (varc
*2 + 200 > vard
){
1104 mb_type
|= MB_TYPE_INTER
;
1105 s
->me
.sub_motion_search(s
, &mx
, &my
, dmin
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1106 pred_x
, pred_y
, &s
->last_picture
, 0, 0, mv_penalty
);
1107 if(s
->flags
&CODEC_FLAG_MV0
)
1109 mb_type
|= MB_TYPE_SKIPED
; //FIXME check difference
1114 if((s
->flags
&CODEC_FLAG_4MV
)
1115 && !s
->me
.skip
&& varc
>50 && vard
>10){
1116 if(h263_mv4_search(s
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
, mx
, my
, shift
) < INT_MAX
)
1117 mb_type
|=MB_TYPE_INTER4V
;
1119 set_p_mv_tables(s
, mx
, my
, 0);
1121 set_p_mv_tables(s
, mx
, my
, 1);
1124 mb_type
= MB_TYPE_INTER
;
1126 dmin
= s
->me
.sub_motion_search(s
, &mx
, &my
, dmin
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1127 pred_x
, pred_y
, &s
->last_picture
, 0, 0, mv_penalty
);
1129 if(s
->avctx
->me_sub_cmp
!= s
->avctx
->mb_cmp
&& !s
->me
.skip
)
1130 dmin
= s
->me
.get_mb_score(s
, mx
, my
, pred_x
, pred_y
, &s
->last_picture
, mv_penalty
);
1132 if((s
->flags
&CODEC_FLAG_4MV
)
1133 && !s
->me
.skip
&& varc
>50 && vard
>10){
1134 int dmin4
= h263_mv4_search(s
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
, mx
, my
, shift
);
1136 mb_type
= MB_TYPE_INTER4V
;
1141 // pic->mb_cmp_score[s->mb_stride * mb_y + mb_x] = dmin;
1142 set_p_mv_tables(s
, mx
, my
, mb_type
!=MB_TYPE_INTER4V
);
1144 /* get intra luma score */
1145 if((s
->avctx
->mb_cmp
&0xFF)==FF_CMP_SSE
){
1146 intra_score
= (varc
<<8) - 500; //FIXME dont scale it down so we dont have to fix it
1148 int mean
= (sum
+128)>>8;
1151 for(i
=0; i
<16; i
++){
1152 *(uint32_t*)(&s
->me
.scratchpad
[i
*s
->linesize
+ 0]) = mean
;
1153 *(uint32_t*)(&s
->me
.scratchpad
[i
*s
->linesize
+ 4]) = mean
;
1154 *(uint32_t*)(&s
->me
.scratchpad
[i
*s
->linesize
+ 8]) = mean
;
1155 *(uint32_t*)(&s
->me
.scratchpad
[i
*s
->linesize
+12]) = mean
;
1158 intra_score
= s
->dsp
.mb_cmp
[0](s
, s
->me
.scratchpad
, pix
, s
->linesize
);
1161 /* get chroma score */
1162 if(s
->avctx
->mb_cmp
&FF_CMP_CHROMA
){
1167 if(s
->out_format
== FMT_H263
){
1168 mean
= (s
->dc_val
[i
][mb_x
+ (mb_y
+1)*(s
->mb_width
+2)] + 4)>>3; //FIXME not exact but simple ;)
1170 mean
= (s
->last_dc
[i
] + 4)>>3;
1172 dest_c
= s
->new_picture
.data
[i
] + (mb_y
* 8 * (s
->uvlinesize
)) + mb_x
* 8;
1176 *(uint32_t*)(&s
->me
.scratchpad
[i
*s
->uvlinesize
+ 0]) = mean
;
1177 *(uint32_t*)(&s
->me
.scratchpad
[i
*s
->uvlinesize
+ 4]) = mean
;
1180 intra_score
+= s
->dsp
.mb_cmp
[1](s
, s
->me
.scratchpad
, dest_c
, s
->uvlinesize
);
1184 intra_score
+= s
->me
.mb_penalty_factor
*16;
1186 if(intra_score
< dmin
){
1187 mb_type
= MB_TYPE_INTRA
;
1188 s
->current_picture
.mb_type
[mb_y
*s
->mb_stride
+ mb_x
]= MB_TYPE_INTRA
; //FIXME cleanup
1190 s
->current_picture
.mb_type
[mb_y
*s
->mb_stride
+ mb_x
]= 0;
1192 if (vard
<= 64 || vard
< varc
) { //FIXME
1193 s
->scene_change_score
+= ff_sqrt(vard
) - ff_sqrt(varc
);
1195 s
->scene_change_score
+= s
->qscale
;
1199 s
->mb_type
[mb_y
*s
->mb_stride
+ mb_x
]= mb_type
;
1202 int ff_pre_estimate_p_frame_motion(MpegEncContext
* s
,
1205 int mx
, my
, range
, dmin
;
1206 int xmin
, ymin
, xmax
, ymax
;
1207 int rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
;
1208 int pred_x
=0, pred_y
=0;
1210 const int shift
= 1+s
->quarter_sample
;
1211 uint8_t * const mv_penalty
= s
->me
.mv_penalty
[s
->f_code
] + MAX_MV
;
1212 const int xy
= mb_x
+ mb_y
*s
->mb_stride
;
1214 assert(s
->quarter_sample
==0 || s
->quarter_sample
==1);
1216 s
->me
.pre_penalty_factor
= get_penalty_factor(s
, s
->avctx
->me_pre_cmp
);
1218 get_limits(s
, &range
, &xmin
, &ymin
, &xmax
, &ymax
);
1219 rel_xmin
= xmin
- mb_x
*16;
1220 rel_xmax
= xmax
- mb_x
*16;
1221 rel_ymin
= ymin
- mb_y
*16;
1222 rel_ymax
= ymax
- mb_y
*16;
1225 P_LEFT
[0] = s
->p_mv_table
[xy
+ 1][0];
1226 P_LEFT
[1] = s
->p_mv_table
[xy
+ 1][1];
1228 if(P_LEFT
[0] < (rel_xmin
<<shift
)) P_LEFT
[0] = (rel_xmin
<<shift
);
1230 /* special case for first line */
1231 if (mb_y
== s
->mb_height
-1) {
1234 P_TOP
[0]= P_TOPRIGHT
[0]= P_MEDIAN
[0]=
1235 P_TOP
[1]= P_TOPRIGHT
[1]= P_MEDIAN
[1]= 0; //FIXME
1237 P_TOP
[0] = s
->p_mv_table
[xy
+ s
->mb_stride
][0];
1238 P_TOP
[1] = s
->p_mv_table
[xy
+ s
->mb_stride
][1];
1239 P_TOPRIGHT
[0] = s
->p_mv_table
[xy
+ s
->mb_stride
- 1][0];
1240 P_TOPRIGHT
[1] = s
->p_mv_table
[xy
+ s
->mb_stride
- 1][1];
1241 if(P_TOP
[1] < (rel_ymin
<<shift
)) P_TOP
[1] = (rel_ymin
<<shift
);
1242 if(P_TOPRIGHT
[0] > (rel_xmax
<<shift
)) P_TOPRIGHT
[0]= (rel_xmax
<<shift
);
1243 if(P_TOPRIGHT
[1] < (rel_ymin
<<shift
)) P_TOPRIGHT
[1]= (rel_ymin
<<shift
);
1245 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1246 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1248 pred_x
= P_MEDIAN
[0];
1249 pred_y
= P_MEDIAN
[1];
1251 dmin
= s
->me
.pre_motion_search(s
, 0, &mx
, &my
, P
, pred_x
, pred_y
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1252 &s
->last_picture
, s
->p_mv_table
, (1<<16)>>shift
, mv_penalty
);
1254 s
->p_mv_table
[xy
][0] = mx
<<shift
;
1255 s
->p_mv_table
[xy
][1] = my
<<shift
;
1260 static int ff_estimate_motion_b(MpegEncContext
* s
,
1261 int mb_x
, int mb_y
, int16_t (*mv_table
)[2], Picture
*picture
, int f_code
)
1263 int mx
, my
, range
, dmin
;
1264 int xmin
, ymin
, xmax
, ymax
;
1265 int rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
;
1266 int pred_x
=0, pred_y
=0;
1268 const int shift
= 1+s
->quarter_sample
;
1269 const int mot_stride
= s
->mb_stride
;
1270 const int mot_xy
= mb_y
*mot_stride
+ mb_x
;
1271 uint8_t * const ref_picture
= picture
->data
[0];
1272 uint8_t * const mv_penalty
= s
->me
.mv_penalty
[f_code
] + MAX_MV
;
1275 s
->me
.penalty_factor
= get_penalty_factor(s
, s
->avctx
->me_cmp
);
1276 s
->me
.sub_penalty_factor
= get_penalty_factor(s
, s
->avctx
->me_sub_cmp
);
1277 s
->me
.mb_penalty_factor
= get_penalty_factor(s
, s
->avctx
->mb_cmp
);
1279 get_limits(s
, &range
, &xmin
, &ymin
, &xmax
, &ymax
);
1280 rel_xmin
= xmin
- mb_x
*16;
1281 rel_xmax
= xmax
- mb_x
*16;
1282 rel_ymin
= ymin
- mb_y
*16;
1283 rel_ymax
= ymax
- mb_y
*16;
1285 switch(s
->me_method
) {
1288 no_motion_search(s
, &mx
, &my
);
1294 dmin
= full_motion_search(s
, &mx
, &my
, range
, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1299 dmin
= log_motion_search(s
, &mx
, &my
, range
/ 2, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1304 dmin
= phods_motion_search(s
, &mx
, &my
, range
/ 2, xmin
, ymin
, xmax
, ymax
, ref_picture
);
1311 P_LEFT
[0] = mv_table
[mot_xy
- 1][0];
1312 P_LEFT
[1] = mv_table
[mot_xy
- 1][1];
1314 if(P_LEFT
[0] > (rel_xmax
<<shift
)) P_LEFT
[0] = (rel_xmax
<<shift
);
1316 /* special case for first line */
1318 P_TOP
[0] = mv_table
[mot_xy
- mot_stride
][0];
1319 P_TOP
[1] = mv_table
[mot_xy
- mot_stride
][1];
1320 P_TOPRIGHT
[0] = mv_table
[mot_xy
- mot_stride
+ 1 ][0];
1321 P_TOPRIGHT
[1] = mv_table
[mot_xy
- mot_stride
+ 1 ][1];
1322 if(P_TOP
[1] > (rel_ymax
<<shift
)) P_TOP
[1]= (rel_ymax
<<shift
);
1323 if(P_TOPRIGHT
[0] < (rel_xmin
<<shift
)) P_TOPRIGHT
[0]= (rel_xmin
<<shift
);
1324 if(P_TOPRIGHT
[1] > (rel_ymax
<<shift
)) P_TOPRIGHT
[1]= (rel_ymax
<<shift
);
1326 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1327 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1333 if(mv_table
== s
->b_forw_mv_table
){
1334 mv_scale
= (s
->pb_time
<<16) / (s
->pp_time
<<shift
);
1336 mv_scale
= ((s
->pb_time
- s
->pp_time
)<<16) / (s
->pp_time
<<shift
);
1339 dmin
= s
->me
.motion_search
[0](s
, 0, &mx
, &my
, P
, pred_x
, pred_y
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1340 picture
, s
->p_mv_table
, mv_scale
, mv_penalty
);
1345 dmin
= s
->me
.sub_motion_search(s
, &mx
, &my
, dmin
, rel_xmin
, rel_ymin
, rel_xmax
, rel_ymax
,
1346 pred_x
, pred_y
, picture
, 0, 0, mv_penalty
);
1348 if(s
->avctx
->me_sub_cmp
!= s
->avctx
->mb_cmp
&& !s
->me
.skip
)
1349 dmin
= s
->me
.get_mb_score(s
, mx
, my
, pred_x
, pred_y
, picture
, mv_penalty
);
1351 //printf("%d %d %d %d//", s->mb_x, s->mb_y, mx, my);
1352 // s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
1353 mv_table
[mot_xy
][0]= mx
;
1354 mv_table
[mot_xy
][1]= my
;
1359 static inline int check_bidir_mv(MpegEncContext
* s
,
1361 int motion_fx
, int motion_fy
,
1362 int motion_bx
, int motion_by
,
1363 int pred_fx
, int pred_fy
,
1364 int pred_bx
, int pred_by
)
1367 //FIXME move into template?
1368 //FIXME better f_code prediction (max mv & distance)
1369 uint8_t * const mv_penalty
= s
->me
.mv_penalty
[s
->f_code
] + MAX_MV
; // f_code of the prev frame
1370 uint8_t *dest_y
= s
->me
.scratchpad
;
1376 if(s
->quarter_sample
){
1377 dxy
= ((motion_fy
& 3) << 2) | (motion_fx
& 3);
1378 src_x
= mb_x
* 16 + (motion_fx
>> 2);
1379 src_y
= mb_y
* 16 + (motion_fy
>> 2);
1380 assert(src_x
>=-16 && src_x
<=s
->h_edge_pos
);
1381 assert(src_y
>=-16 && src_y
<=s
->v_edge_pos
);
1383 ptr
= s
->last_picture
.data
[0] + (src_y
* s
->linesize
) + src_x
;
1384 s
->dsp
.put_qpel_pixels_tab
[0][dxy
](dest_y
, ptr
, s
->linesize
);
1386 dxy
= ((motion_by
& 3) << 2) | (motion_bx
& 3);
1387 src_x
= mb_x
* 16 + (motion_bx
>> 2);
1388 src_y
= mb_y
* 16 + (motion_by
>> 2);
1389 assert(src_x
>=-16 && src_x
<=s
->h_edge_pos
);
1390 assert(src_y
>=-16 && src_y
<=s
->v_edge_pos
);
1392 ptr
= s
->next_picture
.data
[0] + (src_y
* s
->linesize
) + src_x
;
1393 s
->dsp
.avg_qpel_pixels_tab
[0][dxy
](dest_y
, ptr
, s
->linesize
);
1395 dxy
= ((motion_fy
& 1) << 1) | (motion_fx
& 1);
1396 src_x
= mb_x
* 16 + (motion_fx
>> 1);
1397 src_y
= mb_y
* 16 + (motion_fy
>> 1);
1398 assert(src_x
>=-16 && src_x
<=s
->h_edge_pos
);
1399 assert(src_y
>=-16 && src_y
<=s
->v_edge_pos
);
1401 ptr
= s
->last_picture
.data
[0] + (src_y
* s
->linesize
) + src_x
;
1402 s
->dsp
.put_pixels_tab
[0][dxy
](dest_y
, ptr
, s
->linesize
, 16);
1404 dxy
= ((motion_by
& 1) << 1) | (motion_bx
& 1);
1405 src_x
= mb_x
* 16 + (motion_bx
>> 1);
1406 src_y
= mb_y
* 16 + (motion_by
>> 1);
1407 assert(src_x
>=-16 && src_x
<=s
->h_edge_pos
);
1408 assert(src_y
>=-16 && src_y
<=s
->v_edge_pos
);
1410 ptr
= s
->next_picture
.data
[0] + (src_y
* s
->linesize
) + src_x
;
1411 s
->dsp
.avg_pixels_tab
[0][dxy
](dest_y
, ptr
, s
->linesize
, 16);
1414 fbmin
= (mv_penalty
[motion_fx
-pred_fx
] + mv_penalty
[motion_fy
-pred_fy
])*s
->me
.mb_penalty_factor
1415 +(mv_penalty
[motion_bx
-pred_bx
] + mv_penalty
[motion_by
-pred_by
])*s
->me
.mb_penalty_factor
1416 + s
->dsp
.mb_cmp
[0](s
, s
->new_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
, dest_y
, s
->linesize
);
1418 if(s
->avctx
->mb_cmp
&FF_CMP_CHROMA
){
1425 /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1426 static inline int bidir_refine(MpegEncContext
* s
,
1429 const int mot_stride
= s
->mb_stride
;
1430 const int xy
= mb_y
*mot_stride
+ mb_x
;
1432 int pred_fx
= s
->b_bidir_forw_mv_table
[xy
-1][0];
1433 int pred_fy
= s
->b_bidir_forw_mv_table
[xy
-1][1];
1434 int pred_bx
= s
->b_bidir_back_mv_table
[xy
-1][0];
1435 int pred_by
= s
->b_bidir_back_mv_table
[xy
-1][1];
1436 int motion_fx
= s
->b_bidir_forw_mv_table
[xy
][0]= s
->b_forw_mv_table
[xy
][0];
1437 int motion_fy
= s
->b_bidir_forw_mv_table
[xy
][1]= s
->b_forw_mv_table
[xy
][1];
1438 int motion_bx
= s
->b_bidir_back_mv_table
[xy
][0]= s
->b_back_mv_table
[xy
][0];
1439 int motion_by
= s
->b_bidir_back_mv_table
[xy
][1]= s
->b_back_mv_table
[xy
][1];
1441 //FIXME do refinement and add flag
1443 fbmin
= check_bidir_mv(s
, mb_x
, mb_y
,
1444 motion_fx
, motion_fy
,
1445 motion_bx
, motion_by
,
1452 static inline int direct_search(MpegEncContext
* s
,
1456 const int mot_stride
= s
->mb_stride
;
1457 const int mot_xy
= mb_y
*mot_stride
+ mb_x
;
1458 const int shift
= 1+s
->quarter_sample
;
1460 const int time_pp
= s
->pp_time
;
1461 const int time_pb
= s
->pb_time
;
1462 int mx
, my
, xmin
, xmax
, ymin
, ymax
;
1463 int16_t (*mv_table
)[2]= s
->b_direct_mv_table
;
1464 uint8_t * const mv_penalty
= s
->me
.mv_penalty
[1] + MAX_MV
;
1466 ymin
= xmin
=(-32)>>shift
;
1467 ymax
= xmax
= 31>>shift
;
1469 if(IS_8X8(s
->next_picture
.mb_type
[mot_xy
])){
1470 s
->mv_type
= MV_TYPE_8X8
;
1472 s
->mv_type
= MV_TYPE_16X16
;
1476 int index
= s
->block_index
[i
];
1479 s
->me
.co_located_mv
[i
][0]= s
->next_picture
.motion_val
[0][index
][0];
1480 s
->me
.co_located_mv
[i
][1]= s
->next_picture
.motion_val
[0][index
][1];
1481 s
->me
.direct_basis_mv
[i
][0]= s
->me
.co_located_mv
[i
][0]*time_pb
/time_pp
+ ((i
& 1)<<(shift
+3));
1482 s
->me
.direct_basis_mv
[i
][1]= s
->me
.co_located_mv
[i
][1]*time_pb
/time_pp
+ ((i
>>1)<<(shift
+3));
1483 // s->me.direct_basis_mv[1][i][0]= s->me.co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
1484 // s->me.direct_basis_mv[1][i][1]= s->me.co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);
1486 max
= FFMAX(s
->me
.direct_basis_mv
[i
][0], s
->me
.direct_basis_mv
[i
][0] - s
->me
.co_located_mv
[i
][0])>>shift
;
1487 min
= FFMIN(s
->me
.direct_basis_mv
[i
][0], s
->me
.direct_basis_mv
[i
][0] - s
->me
.co_located_mv
[i
][0])>>shift
;
1488 max
+= (2*mb_x
+ (i
& 1))*8 + 1; // +-1 is for the simpler rounding
1489 min
+= (2*mb_x
+ (i
& 1))*8 - 1;
1490 xmax
= FFMIN(xmax
, s
->width
- max
);
1491 xmin
= FFMAX(xmin
, - 16 - min
);
1493 max
= FFMAX(s
->me
.direct_basis_mv
[i
][1], s
->me
.direct_basis_mv
[i
][1] - s
->me
.co_located_mv
[i
][1])>>shift
;
1494 min
= FFMIN(s
->me
.direct_basis_mv
[i
][1], s
->me
.direct_basis_mv
[i
][1] - s
->me
.co_located_mv
[i
][1])>>shift
;
1495 max
+= (2*mb_y
+ (i
>>1))*8 + 1; // +-1 is for the simpler rounding
1496 min
+= (2*mb_y
+ (i
>>1))*8 - 1;
1497 ymax
= FFMIN(ymax
, s
->height
- max
);
1498 ymin
= FFMAX(ymin
, - 16 - min
);
1500 if(s
->mv_type
== MV_TYPE_16X16
) break;
1503 assert(xmax
<= 15 && ymax
<= 15 && xmin
>= -16 && ymin
>= -16);
1505 if(xmax
< 0 || xmin
>0 || ymax
< 0 || ymin
> 0){
1506 s
->b_direct_mv_table
[mot_xy
][0]= 0;
1507 s
->b_direct_mv_table
[mot_xy
][1]= 0;
1509 return 256*256*256*64;
1512 P_LEFT
[0] = clip(mv_table
[mot_xy
- 1][0], xmin
<<shift
, xmax
<<shift
);
1513 P_LEFT
[1] = clip(mv_table
[mot_xy
- 1][1], ymin
<<shift
, ymax
<<shift
);
1515 /* special case for first line */
1517 P_TOP
[0] = clip(mv_table
[mot_xy
- mot_stride
][0], xmin
<<shift
, xmax
<<shift
);
1518 P_TOP
[1] = clip(mv_table
[mot_xy
- mot_stride
][1], ymin
<<shift
, ymax
<<shift
);
1519 P_TOPRIGHT
[0] = clip(mv_table
[mot_xy
- mot_stride
+ 1 ][0], xmin
<<shift
, xmax
<<shift
);
1520 P_TOPRIGHT
[1] = clip(mv_table
[mot_xy
- mot_stride
+ 1 ][1], ymin
<<shift
, ymax
<<shift
);
1522 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1523 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1526 //FIXME direct_search ptr in context!!! (needed for chroma anyway or this will get messy)
1527 if(s
->flags
&CODEC_FLAG_QPEL
){
1528 dmin
= simple_direct_qpel_epzs_motion_search(s
, 0, &mx
, &my
, P
, 0, 0, xmin
, ymin
, xmax
, ymax
,
1529 &s
->last_picture
, mv_table
, 1<<14, mv_penalty
);
1530 dmin
= simple_direct_qpel_qpel_motion_search(s
, &mx
, &my
, dmin
, xmin
, ymin
, xmax
, ymax
,
1531 0, 0, &s
->last_picture
, 0, 0, mv_penalty
);
1533 if(s
->avctx
->me_sub_cmp
!= s
->avctx
->mb_cmp
&& !s
->me
.skip
)
1534 dmin
= simple_direct_qpel_qpel_get_mb_score(s
, mx
, my
, 0, 0, &s
->last_picture
, mv_penalty
);
1536 dmin
= simple_direct_hpel_epzs_motion_search(s
, 0, &mx
, &my
, P
, 0, 0, xmin
, ymin
, xmax
, ymax
,
1537 &s
->last_picture
, mv_table
, 1<<15, mv_penalty
);
1538 dmin
= simple_direct_hpel_hpel_motion_search(s
, &mx
, &my
, dmin
, xmin
, ymin
, xmax
, ymax
,
1539 0, 0, &s
->last_picture
, 0, 0, mv_penalty
);
1541 if(s
->avctx
->me_sub_cmp
!= s
->avctx
->mb_cmp
&& !s
->me
.skip
)
1542 dmin
= simple_direct_hpel_hpel_get_mb_score(s
, mx
, my
, 0, 0, &s
->last_picture
, mv_penalty
);
1545 s
->b_direct_mv_table
[mot_xy
][0]= mx
;
1546 s
->b_direct_mv_table
[mot_xy
][1]= my
;
1550 void ff_estimate_b_frame_motion(MpegEncContext
* s
,
1553 const int penalty_factor
= s
->me
.mb_penalty_factor
;
1554 int fmin
, bmin
, dmin
, fbmin
;
1558 if (s
->codec_id
== CODEC_ID_MPEG4
)
1559 dmin
= direct_search(s
, mb_x
, mb_y
);
1564 fmin
= ff_estimate_motion_b(s
, mb_x
, mb_y
, s
->b_forw_mv_table
, &s
->last_picture
, s
->f_code
) + 3*penalty_factor
;
1567 bmin
= ff_estimate_motion_b(s
, mb_x
, mb_y
, s
->b_back_mv_table
, &s
->next_picture
, s
->b_code
) + 2*penalty_factor
;
1568 //printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1571 fbmin
= bidir_refine(s
, mb_x
, mb_y
) + penalty_factor
;
1572 //printf("%d %d %d %d\n", dmin, fmin, bmin, fbmin);
1575 type
= MB_TYPE_FORWARD
;
1579 type
= MB_TYPE_DIRECT
;
1583 type
= MB_TYPE_BACKWARD
;
1587 type
= MB_TYPE_BIDIR
;
1590 score
= ((unsigned)(score
*score
+ 128*256))>>16;
1591 s
->current_picture
.mc_mb_var_sum
+= score
;
1592 s
->current_picture
.mc_mb_var
[mb_y
*s
->mb_stride
+ mb_x
] = score
; //FIXME use SSE
1595 if(s
->avctx
->mb_decision
> FF_MB_DECISION_SIMPLE
){
1596 type
= MB_TYPE_FORWARD
| MB_TYPE_BACKWARD
| MB_TYPE_BIDIR
| MB_TYPE_DIRECT
; //FIXME something smarter
1597 if(dmin
>256*256*16) type
&= ~MB_TYPE_DIRECT
; //dont try direct mode if its invalid for this MB
1600 s
->mb_type
[mb_y
*s
->mb_stride
+ mb_x
]= type
;
1603 /* find best f_code for ME which do unlimited searches */
1604 int ff_get_best_fcode(MpegEncContext
* s
, int16_t (*mv_table
)[2], int type
)
1606 if(s
->me_method
>=ME_EPZS
){
1609 uint8_t * fcode_tab
= s
->fcode_tab
;
1611 int best_score
=-10000000;
1613 for(i
=0; i
<8; i
++) score
[i
]= s
->mb_num
*(8-i
);
1615 for(y
=0; y
<s
->mb_height
; y
++){
1617 int xy
= y
*s
->mb_stride
;
1618 for(x
=0; x
<s
->mb_width
; x
++){
1619 if(s
->mb_type
[xy
] & type
){
1620 int fcode
= FFMAX(fcode_tab
[mv_table
[xy
][0] + MAX_MV
],
1621 fcode_tab
[mv_table
[xy
][1] + MAX_MV
]);
1624 for(j
=0; j
<fcode
&& j
<8; j
++){
1625 if(s
->pict_type
==B_TYPE
|| s
->current_picture
.mc_mb_var
[xy
] < s
->current_picture
.mb_var
[xy
])
1634 if(score
[i
] > best_score
){
1635 best_score
= score
[i
];
1638 // printf("%d %d\n", i, score[i]);
1641 // printf("fcode: %d type: %d\n", i, s->pict_type);
1643 /* for(i=0; i<=MAX_FCODE; i++){
1644 printf("%d ", mv_num[i]);
1652 void ff_fix_long_p_mvs(MpegEncContext
* s
)
1654 const int f_code
= s
->f_code
;
1656 assert(s
->pict_type
==P_TYPE
);
1658 range
= (((s
->out_format
== FMT_MPEG1
) ?
8 : 16) << f_code
);
1660 if(s
->msmpeg4_version
) range
= 16;
1662 if(s
->avctx
->me_range
&& range
> s
->avctx
->me_range
) range
= s
->avctx
->me_range
;
1664 /* clip / convert to intra 16x16 type MVs */
1665 for(y
=0; y
<s
->mb_height
; y
++){
1667 int xy
= y
*s
->mb_stride
;
1668 for(x
=0; x
<s
->mb_width
; x
++){
1669 if(s
->mb_type
[xy
]&MB_TYPE_INTER
){
1670 if( s
->p_mv_table
[xy
][0] >=range
|| s
->p_mv_table
[xy
][0] <-range
1671 || s
->p_mv_table
[xy
][1] >=range
|| s
->p_mv_table
[xy
][1] <-range
){
1672 s
->mb_type
[xy
] &= ~MB_TYPE_INTER
;
1673 s
->mb_type
[xy
] |= MB_TYPE_INTRA
;
1674 s
->current_picture
.mb_type
[xy
]= MB_TYPE_INTRA
;
1675 s
->p_mv_table
[xy
][0] = 0;
1676 s
->p_mv_table
[xy
][1] = 0;
1682 //printf("%d no:%d %d//\n", clip, noclip, f_code);
1683 if(s
->flags
&CODEC_FLAG_4MV
){
1684 const int wrap
= 2+ s
->mb_width
*2;
1686 /* clip / convert to intra 8x8 type MVs */
1687 for(y
=0; y
<s
->mb_height
; y
++){
1688 int xy
= (y
*2 + 1)*wrap
+ 1;
1689 int i
= y
*s
->mb_stride
;
1692 for(x
=0; x
<s
->mb_width
; x
++){
1693 if(s
->mb_type
[i
]&MB_TYPE_INTER4V
){
1695 for(block
=0; block
<4; block
++){
1696 int off
= (block
& 1) + (block
>>1)*wrap
;
1697 int mx
= s
->current_picture
.motion_val
[0][ xy
+ off
][0];
1698 int my
= s
->current_picture
.motion_val
[0][ xy
+ off
][1];
1700 if( mx
>=range
|| mx
<-range
1701 || my
>=range
|| my
<-range
){
1702 s
->mb_type
[i
] &= ~MB_TYPE_INTER4V
;
1703 s
->mb_type
[i
] |= MB_TYPE_INTRA
;
1704 s
->current_picture
.mb_type
[i
]= MB_TYPE_INTRA
;
1715 void ff_fix_long_b_mvs(MpegEncContext
* s
, int16_t (*mv_table
)[2], int f_code
, int type
)
1719 // RAL: 8 in MPEG-1, 16 in MPEG-4
1720 int range
= (((s
->out_format
== FMT_MPEG1
) ?
8 : 16) << f_code
);
1722 if(s
->avctx
->me_range
&& range
> s
->avctx
->me_range
) range
= s
->avctx
->me_range
;
1724 /* clip / convert to intra 16x16 type MVs */
1725 for(y
=0; y
<s
->mb_height
; y
++){
1727 int xy
= y
*s
->mb_stride
;
1728 for(x
=0; x
<s
->mb_width
; x
++){
1729 if (s
->mb_type
[xy
] & type
){ // RAL: "type" test added...
1730 if( mv_table
[xy
][0] >=range
|| mv_table
[xy
][0] <-range
1731 || mv_table
[xy
][1] >=range
|| mv_table
[xy
][1] <-range
){
1733 if(s
->codec_id
== CODEC_ID_MPEG1VIDEO
&& 0){
1735 if (mv_table
[xy
][0] > range
-1) mv_table
[xy
][0]= range
-1;
1736 else if(mv_table
[xy
][0] < -range
) mv_table
[xy
][0]= -range
;
1737 if (mv_table
[xy
][1] > range
-1) mv_table
[xy
][1]= range
-1;
1738 else if(mv_table
[xy
][1] < -range
) mv_table
[xy
][1]= -range
;