3 * Copyright (c) 2000,2001 Fabrice Bellard
4 * Copyright (c) 2002-2004 Michael Niedermayer
6 * new motion estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
8 * This file is part of FFmpeg.
10 * FFmpeg is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * FFmpeg is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with FFmpeg; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
36 #include "mpegutils.h"
37 #include "mpegvideo.h"
44 #define P_TOPRIGHT P[3]
48 #define ME_MAP_SHIFT 3
49 #define ME_MAP_MV_BITS 11
51 static int sad_hpel_motion_search(MpegEncContext
* s
,
52 int *mx_ptr
, int *my_ptr
, int dmin
,
53 int src_index
, int ref_index
,
56 static inline unsigned update_map_generation(MotionEstContext
*c
)
58 c
->map_generation
+= 1<<(ME_MAP_MV_BITS
*2);
59 if(c
->map_generation
==0){
60 c
->map_generation
= 1<<(ME_MAP_MV_BITS
*2);
61 memset(c
->map
, 0, sizeof(uint32_t)*ME_MAP_SIZE
);
63 return c
->map_generation
;
66 /* shape adaptive search stuff */
67 typedef struct Minima
{
73 static int minima_cmp(const void *a
, const void *b
){
74 const Minima
*da
= (const Minima
*) a
;
75 const Minima
*db
= (const Minima
*) b
;
77 return da
->height
- db
->height
;
80 #define FLAG_QPEL 1 //must be 1
84 static inline void init_ref(MotionEstContext
*c
, uint8_t *src
[3], uint8_t *ref
[3], uint8_t *ref2
[3], int x
, int y
, int ref_index
){
85 const int offset
[3]= {
87 ((y
*c
->uvstride
+ x
)>>1),
88 ((y
*c
->uvstride
+ x
)>>1),
92 c
->src
[0][i
]= src
[i
] + offset
[i
];
93 c
->ref
[0][i
]= ref
[i
] + offset
[i
];
97 c
->ref
[ref_index
][i
]= ref2
[i
] + offset
[i
];
102 static int get_flags(MotionEstContext
*c
, int direct
, int chroma
){
103 return ((c
->avctx
->flags
&CODEC_FLAG_QPEL
) ? FLAG_QPEL
: 0)
104 + (direct
? FLAG_DIRECT
: 0)
105 + (chroma
? FLAG_CHROMA
: 0);
108 static av_always_inline
int cmp_direct_inline(MpegEncContext
*s
, const int x
, const int y
, const int subx
, const int suby
,
109 const int size
, const int h
, int ref_index
, int src_index
,
110 me_cmp_func cmp_func
, me_cmp_func chroma_cmp_func
, int qpel
){
111 MotionEstContext
* const c
= &s
->me
;
112 const int stride
= c
->stride
;
113 const int hx
= subx
+ (x
<<(1+qpel
));
114 const int hy
= suby
+ (y
<<(1+qpel
));
115 uint8_t * const * const ref
= c
->ref
[ref_index
];
116 uint8_t * const * const src
= c
->src
[src_index
];
118 //FIXME check chroma 4mv, (no crashes ...)
119 av_assert2(x
>= c
->xmin
&& hx
<= c
->xmax
<<(qpel
+1) && y
>= c
->ymin
&& hy
<= c
->ymax
<<(qpel
+1));
120 if(x
>= c
->xmin
&& hx
<= c
->xmax
<<(qpel
+1) && y
>= c
->ymin
&& hy
<= c
->ymax
<<(qpel
+1)){
121 const int time_pp
= s
->pp_time
;
122 const int time_pb
= s
->pb_time
;
123 const int mask
= 2*qpel
+1;
124 if(s
->mv_type
==MV_TYPE_8X8
){
127 int fx
= c
->direct_basis_mv
[i
][0] + hx
;
128 int fy
= c
->direct_basis_mv
[i
][1] + hy
;
129 int bx
= hx
? fx
- c
->co_located_mv
[i
][0] : c
->co_located_mv
[i
][0]*(time_pb
- time_pp
)/time_pp
+ ((i
&1)<<(qpel
+4));
130 int by
= hy
? fy
- c
->co_located_mv
[i
][1] : c
->co_located_mv
[i
][1]*(time_pb
- time_pp
)/time_pp
+ ((i
>>1)<<(qpel
+4));
131 int fxy
= (fx
&mask
) + ((fy
&mask
)<<(qpel
+1));
132 int bxy
= (bx
&mask
) + ((by
&mask
)<<(qpel
+1));
134 uint8_t *dst
= c
->temp
+ 8*(i
&1) + 8*stride
*(i
>>1);
136 c
->qpel_put
[1][fxy
](dst
, ref
[0] + (fx
>>2) + (fy
>>2)*stride
, stride
);
137 c
->qpel_avg
[1][bxy
](dst
, ref
[8] + (bx
>>2) + (by
>>2)*stride
, stride
);
139 c
->hpel_put
[1][fxy
](dst
, ref
[0] + (fx
>>1) + (fy
>>1)*stride
, stride
, 8);
140 c
->hpel_avg
[1][bxy
](dst
, ref
[8] + (bx
>>1) + (by
>>1)*stride
, stride
, 8);
144 int fx
= c
->direct_basis_mv
[0][0] + hx
;
145 int fy
= c
->direct_basis_mv
[0][1] + hy
;
146 int bx
= hx
? fx
- c
->co_located_mv
[0][0] : (c
->co_located_mv
[0][0]*(time_pb
- time_pp
)/time_pp
);
147 int by
= hy
? fy
- c
->co_located_mv
[0][1] : (c
->co_located_mv
[0][1]*(time_pb
- time_pp
)/time_pp
);
148 int fxy
= (fx
&mask
) + ((fy
&mask
)<<(qpel
+1));
149 int bxy
= (bx
&mask
) + ((by
&mask
)<<(qpel
+1));
152 c
->qpel_put
[1][fxy
](c
->temp
, ref
[0] + (fx
>>2) + (fy
>>2)*stride
, stride
);
153 c
->qpel_put
[1][fxy
](c
->temp
+ 8 , ref
[0] + (fx
>>2) + (fy
>>2)*stride
+ 8 , stride
);
154 c
->qpel_put
[1][fxy
](c
->temp
+ 8*stride
, ref
[0] + (fx
>>2) + (fy
>>2)*stride
+ 8*stride
, stride
);
155 c
->qpel_put
[1][fxy
](c
->temp
+ 8 + 8*stride
, ref
[0] + (fx
>>2) + (fy
>>2)*stride
+ 8 + 8*stride
, stride
);
156 c
->qpel_avg
[1][bxy
](c
->temp
, ref
[8] + (bx
>>2) + (by
>>2)*stride
, stride
);
157 c
->qpel_avg
[1][bxy
](c
->temp
+ 8 , ref
[8] + (bx
>>2) + (by
>>2)*stride
+ 8 , stride
);
158 c
->qpel_avg
[1][bxy
](c
->temp
+ 8*stride
, ref
[8] + (bx
>>2) + (by
>>2)*stride
+ 8*stride
, stride
);
159 c
->qpel_avg
[1][bxy
](c
->temp
+ 8 + 8*stride
, ref
[8] + (bx
>>2) + (by
>>2)*stride
+ 8 + 8*stride
, stride
);
161 av_assert2((fx
>>1) + 16*s
->mb_x
>= -16);
162 av_assert2((fy
>>1) + 16*s
->mb_y
>= -16);
163 av_assert2((fx
>>1) + 16*s
->mb_x
<= s
->width
);
164 av_assert2((fy
>>1) + 16*s
->mb_y
<= s
->height
);
165 av_assert2((bx
>>1) + 16*s
->mb_x
>= -16);
166 av_assert2((by
>>1) + 16*s
->mb_y
>= -16);
167 av_assert2((bx
>>1) + 16*s
->mb_x
<= s
->width
);
168 av_assert2((by
>>1) + 16*s
->mb_y
<= s
->height
);
170 c
->hpel_put
[0][fxy
](c
->temp
, ref
[0] + (fx
>>1) + (fy
>>1)*stride
, stride
, 16);
171 c
->hpel_avg
[0][bxy
](c
->temp
, ref
[8] + (bx
>>1) + (by
>>1)*stride
, stride
, 16);
174 d
= cmp_func(s
, c
->temp
, src
[0], stride
, 16);
180 static av_always_inline
int cmp_inline(MpegEncContext
*s
, const int x
, const int y
, const int subx
, const int suby
,
181 const int size
, const int h
, int ref_index
, int src_index
,
182 me_cmp_func cmp_func
, me_cmp_func chroma_cmp_func
, int qpel
, int chroma
){
183 MotionEstContext
* const c
= &s
->me
;
184 const int stride
= c
->stride
;
185 const int uvstride
= c
->uvstride
;
186 const int dxy
= subx
+ (suby
<<(1+qpel
)); //FIXME log2_subpel?
187 const int hx
= subx
+ (x
<<(1+qpel
));
188 const int hy
= suby
+ (y
<<(1+qpel
));
189 uint8_t * const * const ref
= c
->ref
[ref_index
];
190 uint8_t * const * const src
= c
->src
[src_index
];
192 //FIXME check chroma 4mv, (no crashes ...)
193 int uvdxy
; /* no, it might not be used uninitialized */
196 if (h
<< size
== 16) {
197 c
->qpel_put
[size
][dxy
](c
->temp
, ref
[0] + x
+ y
*stride
, stride
); //FIXME prototype (add h)
198 } else if (size
== 0 && h
== 8) {
199 c
->qpel_put
[1][dxy
](c
->temp
, ref
[0] + x
+ y
*stride
, stride
);
200 c
->qpel_put
[1][dxy
](c
->temp
+ 8, ref
[0] + x
+ y
*stride
+ 8, stride
);
208 uvdxy
= (cx
&1) + 2*(cy
&1);
209 //FIXME x/y wrong, but mpeg4 qpel is sick anyway, we should drop as much of it as possible in favor for h264
212 c
->hpel_put
[size
][dxy
](c
->temp
, ref
[0] + x
+ y
*stride
, stride
, h
);
214 uvdxy
= dxy
| (x
&1) | (2*(y
&1));
216 d
= cmp_func(s
, c
->temp
, src
[0], stride
, h
);
218 d
= cmp_func(s
, src
[0], ref
[0] + x
+ y
*stride
, stride
, h
);
220 uvdxy
= (x
&1) + 2*(y
&1);
223 uint8_t * const uvtemp
= c
->temp
+ 16*stride
;
224 c
->hpel_put
[size
+1][uvdxy
](uvtemp
, ref
[1] + (x
>>1) + (y
>>1)*uvstride
, uvstride
, h
>>1);
225 c
->hpel_put
[size
+1][uvdxy
](uvtemp
+8, ref
[2] + (x
>>1) + (y
>>1)*uvstride
, uvstride
, h
>>1);
226 d
+= chroma_cmp_func(s
, uvtemp
, src
[1], uvstride
, h
>>1);
227 d
+= chroma_cmp_func(s
, uvtemp
+8, src
[2], uvstride
, h
>>1);
232 static int cmp_simple(MpegEncContext
*s
, const int x
, const int y
,
233 int ref_index
, int src_index
,
234 me_cmp_func cmp_func
, me_cmp_func chroma_cmp_func
){
235 return cmp_inline(s
,x
,y
,0,0,0,16,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, 0, 0);
238 static int cmp_fpel_internal(MpegEncContext
*s
, const int x
, const int y
,
239 const int size
, const int h
, int ref_index
, int src_index
,
240 me_cmp_func cmp_func
, me_cmp_func chroma_cmp_func
, const int flags
){
241 if(flags
&FLAG_DIRECT
){
242 return cmp_direct_inline(s
,x
,y
,0,0,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, flags
&FLAG_QPEL
);
244 return cmp_inline(s
,x
,y
,0,0,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, 0, flags
&FLAG_CHROMA
);
248 static int cmp_internal(MpegEncContext
*s
, const int x
, const int y
, const int subx
, const int suby
,
249 const int size
, const int h
, int ref_index
, int src_index
,
250 me_cmp_func cmp_func
, me_cmp_func chroma_cmp_func
, const int flags
){
251 if(flags
&FLAG_DIRECT
){
252 return cmp_direct_inline(s
,x
,y
,subx
,suby
,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, flags
&FLAG_QPEL
);
254 return cmp_inline(s
,x
,y
,subx
,suby
,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, flags
&FLAG_QPEL
, flags
&FLAG_CHROMA
);
258 /** @brief compares a block (either a full macroblock or a partition thereof)
259 against a proposed motion-compensated prediction of that block
261 static av_always_inline
int cmp(MpegEncContext
*s
, const int x
, const int y
, const int subx
, const int suby
,
262 const int size
, const int h
, int ref_index
, int src_index
,
263 me_cmp_func cmp_func
, me_cmp_func chroma_cmp_func
, const int flags
){
264 if(av_builtin_constant_p(flags
) && av_builtin_constant_p(h
) && av_builtin_constant_p(size
)
265 && av_builtin_constant_p(subx
) && av_builtin_constant_p(suby
)
266 && flags
==0 && h
==16 && size
==0 && subx
==0 && suby
==0){
267 return cmp_simple(s
,x
,y
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
);
268 }else if(av_builtin_constant_p(subx
) && av_builtin_constant_p(suby
)
269 && subx
==0 && suby
==0){
270 return cmp_fpel_internal(s
,x
,y
,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
,flags
);
272 return cmp_internal(s
,x
,y
,subx
,suby
,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, flags
);
276 static int cmp_hpel(MpegEncContext
*s
, const int x
, const int y
, const int subx
, const int suby
,
277 const int size
, const int h
, int ref_index
, int src_index
,
278 me_cmp_func cmp_func
, me_cmp_func chroma_cmp_func
, const int flags
){
279 if(flags
&FLAG_DIRECT
){
280 return cmp_direct_inline(s
,x
,y
,subx
,suby
,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, 0);
282 return cmp_inline(s
,x
,y
,subx
,suby
,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, 0, flags
&FLAG_CHROMA
);
286 static int cmp_qpel(MpegEncContext
*s
, const int x
, const int y
, const int subx
, const int suby
,
287 const int size
, const int h
, int ref_index
, int src_index
,
288 me_cmp_func cmp_func
, me_cmp_func chroma_cmp_func
, const int flags
){
289 if(flags
&FLAG_DIRECT
){
290 return cmp_direct_inline(s
,x
,y
,subx
,suby
,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, 1);
292 return cmp_inline(s
,x
,y
,subx
,suby
,size
,h
,ref_index
,src_index
, cmp_func
, chroma_cmp_func
, 1, flags
&FLAG_CHROMA
);
296 #include "motion_est_template.c"
298 static int zero_cmp(MpegEncContext
*s
, uint8_t *a
, uint8_t *b
,
299 ptrdiff_t stride
, int h
)
304 static void zero_hpel(uint8_t *a
, const uint8_t *b
, ptrdiff_t stride
, int h
){
307 int ff_init_me(MpegEncContext
*s
){
308 MotionEstContext
* const c
= &s
->me
;
309 int cache_size
= FFMIN(ME_MAP_SIZE
>>ME_MAP_SHIFT
, 1<<ME_MAP_SHIFT
);
310 int dia_size
= FFMAX(FFABS(s
->avctx
->dia_size
)&255, FFABS(s
->avctx
->pre_dia_size
)&255);
312 if(FFMIN(s
->avctx
->dia_size
, s
->avctx
->pre_dia_size
) < -FFMIN(ME_MAP_SIZE
, MAX_SAB_SIZE
)){
313 av_log(s
->avctx
, AV_LOG_ERROR
, "ME_MAP size is too small for SAB diamond\n");
316 //special case of snow is needed because snow uses its own iterative ME code
317 if(s
->me_method
!=ME_ZERO
&& s
->me_method
!=ME_EPZS
&& s
->me_method
!=ME_X1
&& s
->avctx
->codec_id
!= AV_CODEC_ID_SNOW
){
318 av_log(s
->avctx
, AV_LOG_ERROR
, "me_method is only allowed to be set to zero and epzs; for hex,umh,full and others see dia_size\n");
324 if(cache_size
< 2*dia_size
&& !c
->stride
){
325 av_log(s
->avctx
, AV_LOG_INFO
, "ME_MAP size may be a little small for the selected diamond size\n");
328 ff_set_cmp(&s
->mecc
, s
->mecc
.me_pre_cmp
, c
->avctx
->me_pre_cmp
);
329 ff_set_cmp(&s
->mecc
, s
->mecc
.me_cmp
, c
->avctx
->me_cmp
);
330 ff_set_cmp(&s
->mecc
, s
->mecc
.me_sub_cmp
, c
->avctx
->me_sub_cmp
);
331 ff_set_cmp(&s
->mecc
, s
->mecc
.mb_cmp
, c
->avctx
->mb_cmp
);
333 c
->flags
= get_flags(c
, 0, c
->avctx
->me_cmp
&FF_CMP_CHROMA
);
334 c
->sub_flags
= get_flags(c
, 0, c
->avctx
->me_sub_cmp
&FF_CMP_CHROMA
);
335 c
->mb_flags
= get_flags(c
, 0, c
->avctx
->mb_cmp
&FF_CMP_CHROMA
);
337 /*FIXME s->no_rounding b_type*/
338 if(s
->flags
&CODEC_FLAG_QPEL
){
339 c
->sub_motion_search
= qpel_motion_search
;
340 c
->qpel_avg
= s
->qdsp
.avg_qpel_pixels_tab
;
342 c
->qpel_put
= s
->qdsp
.put_no_rnd_qpel_pixels_tab
;
344 c
->qpel_put
= s
->qdsp
.put_qpel_pixels_tab
;
346 if(c
->avctx
->me_sub_cmp
&FF_CMP_CHROMA
)
347 c
->sub_motion_search
= hpel_motion_search
;
348 else if( c
->avctx
->me_sub_cmp
== FF_CMP_SAD
349 && c
->avctx
-> me_cmp
== FF_CMP_SAD
350 && c
->avctx
-> mb_cmp
== FF_CMP_SAD
)
351 c
->sub_motion_search
= sad_hpel_motion_search
; // 2050 vs. 2450 cycles
353 c
->sub_motion_search
= hpel_motion_search
;
355 c
->hpel_avg
= s
->hdsp
.avg_pixels_tab
;
357 c
->hpel_put
= s
->hdsp
.put_no_rnd_pixels_tab
;
359 c
->hpel_put
= s
->hdsp
.put_pixels_tab
;
362 c
->stride
= s
->linesize
;
363 c
->uvstride
= s
->uvlinesize
;
365 c
->stride
= 16*s
->mb_width
+ 32;
366 c
->uvstride
= 8*s
->mb_width
+ 16;
369 /* 8x8 fullpel search would need a 4x4 chroma compare, which we do
370 * not have yet, and even if we had, the motion estimation code
371 * does not expect it. */
372 if (s
->codec_id
!= AV_CODEC_ID_SNOW
) {
373 if ((c
->avctx
->me_cmp
& FF_CMP_CHROMA
) /* && !s->mecc.me_cmp[2] */)
374 s
->mecc
.me_cmp
[2] = zero_cmp
;
375 if ((c
->avctx
->me_sub_cmp
& FF_CMP_CHROMA
) && !s
->mecc
.me_sub_cmp
[2])
376 s
->mecc
.me_sub_cmp
[2] = zero_cmp
;
377 c
->hpel_put
[2][0]= c
->hpel_put
[2][1]=
378 c
->hpel_put
[2][2]= c
->hpel_put
[2][3]= zero_hpel
;
381 if(s
->codec_id
== AV_CODEC_ID_H261
){
382 c
->sub_motion_search
= no_sub_motion_search
;
388 #define CHECK_SAD_HALF_MV(suffix, x, y) \
390 d = s->mecc.pix_abs[size][(x ? 1 : 0) + (y ? 2 : 0)](NULL, pix, ptr + ((x) >> 1), stride, h); \
391 d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\
392 COPY3_IF_LT(dminh, d, dx, x, dy, y)\
395 static int sad_hpel_motion_search(MpegEncContext
* s
,
396 int *mx_ptr
, int *my_ptr
, int dmin
,
397 int src_index
, int ref_index
,
400 MotionEstContext
* const c
= &s
->me
;
401 const int penalty_factor
= c
->sub_penalty_factor
;
404 int stride
= c
->stride
;
407 av_assert2(c
->sub_flags
== 0);
415 pix
= c
->src
[src_index
][0];
419 ptr
= c
->ref
[ref_index
][0] + (my
* stride
) + mx
;
423 if (mx
> xmin
&& mx
< xmax
&&
424 my
> ymin
&& my
< ymax
) {
427 const int index
= (my
<<ME_MAP_SHIFT
) + mx
;
428 const int t
= score_map
[(index
-(1<<ME_MAP_SHIFT
))&(ME_MAP_SIZE
-1)];
429 const int l
= score_map
[(index
- 1 )&(ME_MAP_SIZE
-1)];
430 const int r
= score_map
[(index
+ 1 )&(ME_MAP_SIZE
-1)];
431 const int b
= score_map
[(index
+(1<<ME_MAP_SHIFT
))&(ME_MAP_SIZE
-1)];
441 CHECK_SAD_HALF_MV(y2
, 0, -1)
443 CHECK_SAD_HALF_MV(xy2
, -1, -1)
445 CHECK_SAD_HALF_MV(xy2
, +1, -1)
449 CHECK_SAD_HALF_MV(xy2
, -1, +1)
451 CHECK_SAD_HALF_MV(x2
, -1, 0)
453 CHECK_SAD_HALF_MV(xy2
, +1, -1)
455 CHECK_SAD_HALF_MV(xy2
, -1, -1)
459 CHECK_SAD_HALF_MV(xy2
, +1, +1)
461 CHECK_SAD_HALF_MV(x2
, +1, 0)
466 CHECK_SAD_HALF_MV(xy2
, -1, -1)
470 CHECK_SAD_HALF_MV(xy2
, +1, +1)
472 CHECK_SAD_HALF_MV(x2
, -1, 0)
473 CHECK_SAD_HALF_MV(xy2
, -1, +1)
476 CHECK_SAD_HALF_MV(xy2
, +1, -1)
480 CHECK_SAD_HALF_MV(xy2
, -1, +1)
482 CHECK_SAD_HALF_MV(x2
, +1, 0)
483 CHECK_SAD_HALF_MV(xy2
, +1, +1)
485 CHECK_SAD_HALF_MV(y2
, 0, +1)
500 static inline void set_p_mv_tables(MpegEncContext
* s
, int mx
, int my
, int mv4
)
502 const int xy
= s
->mb_x
+ s
->mb_y
*s
->mb_stride
;
504 s
->p_mv_table
[xy
][0] = mx
;
505 s
->p_mv_table
[xy
][1] = my
;
507 /* has already been set to the 4 MV if 4MV is done */
509 int mot_xy
= s
->block_index
[0];
511 s
->current_picture
.motion_val
[0][mot_xy
][0] = mx
;
512 s
->current_picture
.motion_val
[0][mot_xy
][1] = my
;
513 s
->current_picture
.motion_val
[0][mot_xy
+ 1][0] = mx
;
514 s
->current_picture
.motion_val
[0][mot_xy
+ 1][1] = my
;
516 mot_xy
+= s
->b8_stride
;
517 s
->current_picture
.motion_val
[0][mot_xy
][0] = mx
;
518 s
->current_picture
.motion_val
[0][mot_xy
][1] = my
;
519 s
->current_picture
.motion_val
[0][mot_xy
+ 1][0] = mx
;
520 s
->current_picture
.motion_val
[0][mot_xy
+ 1][1] = my
;
525 * get fullpel ME search limits.
527 static inline void get_limits(MpegEncContext
*s
, int x
, int y
)
529 MotionEstContext
* const c
= &s
->me
;
530 int range
= c
->avctx
->me_range
>> (1 + !!(c
->flags
&FLAG_QPEL
));
531 int max_range
= MAX_MV
>> (1 + !!(c
->flags
&FLAG_QPEL
));
533 if(c->avctx->me_range) c->range= c->avctx->me_range >> 1;
536 if (s
->unrestricted_mv
) {
539 c
->xmax
= - x
+ s
->width
;
540 c
->ymax
= - y
+ s
->height
;
541 } else if (s
->out_format
== FMT_H261
){
542 // Search range of H261 is different from other codec standards
543 c
->xmin
= (x
> 15) ? - 15 : 0;
544 c
->ymin
= (y
> 15) ? - 15 : 0;
545 c
->xmax
= (x
< s
->mb_width
* 16 - 16) ? 15 : 0;
546 c
->ymax
= (y
< s
->mb_height
* 16 - 16) ? 15 : 0;
550 c
->xmax
= - x
+ s
->mb_width
*16 - 16;
551 c
->ymax
= - y
+ s
->mb_height
*16 - 16;
553 if(!range
|| range
> max_range
)
556 c
->xmin
= FFMAX(c
->xmin
,-range
);
557 c
->xmax
= FFMIN(c
->xmax
, range
);
558 c
->ymin
= FFMAX(c
->ymin
,-range
);
559 c
->ymax
= FFMIN(c
->ymax
, range
);
563 static inline void init_mv4_ref(MotionEstContext
*c
){
564 const int stride
= c
->stride
;
566 c
->ref
[1][0] = c
->ref
[0][0] + 8;
567 c
->ref
[2][0] = c
->ref
[0][0] + 8*stride
;
568 c
->ref
[3][0] = c
->ref
[2][0] + 8;
569 c
->src
[1][0] = c
->src
[0][0] + 8;
570 c
->src
[2][0] = c
->src
[0][0] + 8*stride
;
571 c
->src
[3][0] = c
->src
[2][0] + 8;
574 static inline int h263_mv4_search(MpegEncContext
*s
, int mx
, int my
, int shift
)
576 MotionEstContext
* const c
= &s
->me
;
581 int dmin_sum
=0, mx4_sum
=0, my4_sum
=0, i
;
583 const int stride
= c
->stride
;
584 uint8_t *mv_penalty
= c
->current_mv_penalty
;
585 int saftey_cliping
= s
->unrestricted_mv
&& (s
->width
&15) && (s
->height
&15);
589 for(block
=0; block
<4; block
++){
591 int pred_x4
, pred_y4
;
593 static const int off
[4]= {2, 1, 1, -1};
594 const int mot_stride
= s
->b8_stride
;
595 const int mot_xy
= s
->block_index
[block
];
598 c
->xmax
= - 16*s
->mb_x
+ s
->width
- 8*(block
&1);
599 c
->ymax
= - 16*s
->mb_y
+ s
->height
- 8*(block
>>1);
602 P_LEFT
[0] = s
->current_picture
.motion_val
[0][mot_xy
- 1][0];
603 P_LEFT
[1] = s
->current_picture
.motion_val
[0][mot_xy
- 1][1];
605 if(P_LEFT
[0] > (c
->xmax
<<shift
)) P_LEFT
[0] = (c
->xmax
<<shift
);
607 /* special case for first line */
608 if (s
->first_slice_line
&& block
<2) {
609 c
->pred_x
= pred_x4
= P_LEFT
[0];
610 c
->pred_y
= pred_y4
= P_LEFT
[1];
612 P_TOP
[0] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
][0];
613 P_TOP
[1] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
][1];
614 P_TOPRIGHT
[0] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
+ off
[block
]][0];
615 P_TOPRIGHT
[1] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
+ off
[block
]][1];
616 if(P_TOP
[1] > (c
->ymax
<<shift
)) P_TOP
[1] = (c
->ymax
<<shift
);
617 if(P_TOPRIGHT
[0] < (c
->xmin
<<shift
)) P_TOPRIGHT
[0]= (c
->xmin
<<shift
);
618 if(P_TOPRIGHT
[0] > (c
->xmax
<<shift
)) P_TOPRIGHT
[0]= (c
->xmax
<<shift
);
619 if(P_TOPRIGHT
[1] > (c
->ymax
<<shift
)) P_TOPRIGHT
[1]= (c
->ymax
<<shift
);
621 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
622 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
624 c
->pred_x
= pred_x4
= P_MEDIAN
[0];
625 c
->pred_y
= pred_y4
= P_MEDIAN
[1];
631 if (s
->first_slice_line
&& block
<2 && i
>1 && i
<9)
635 if(P
[i
][0] > (c
->xmax
<<shift
)) P
[i
][0]= (c
->xmax
<<shift
);
636 if(P
[i
][1] > (c
->ymax
<<shift
)) P
[i
][1]= (c
->ymax
<<shift
);
639 dmin4
= epzs_motion_search4(s
, &mx4
, &my4
, P
, block
, block
, s
->p_mv_table
, (1<<16)>>shift
);
641 dmin4
= c
->sub_motion_search(s
, &mx4
, &my4
, dmin4
, block
, block
, size
, h
);
643 if (s
->mecc
.me_sub_cmp
[0] != s
->mecc
.mb_cmp
[0]) {
645 const int offset
= ((block
&1) + (block
>>1)*stride
)*8;
646 uint8_t *dest_y
= c
->scratchpad
+ offset
;
647 if(s
->quarter_sample
){
648 uint8_t *ref
= c
->ref
[block
][0] + (mx4
>>2) + (my4
>>2)*stride
;
649 dxy
= ((my4
& 3) << 2) | (mx4
& 3);
652 s
->qdsp
.put_no_rnd_qpel_pixels_tab
[1][dxy
](dest_y
, ref
, stride
);
654 s
->qdsp
.put_qpel_pixels_tab
[1][dxy
](dest_y
, ref
, stride
);
656 uint8_t *ref
= c
->ref
[block
][0] + (mx4
>>1) + (my4
>>1)*stride
;
657 dxy
= ((my4
& 1) << 1) | (mx4
& 1);
660 s
->hdsp
.put_no_rnd_pixels_tab
[1][dxy
](dest_y
, ref
, stride
, h
);
662 s
->hdsp
.put_pixels_tab
[1][dxy
](dest_y
, ref
, stride
, h
);
664 dmin_sum
+= (mv_penalty
[mx4
-pred_x4
] + mv_penalty
[my4
-pred_y4
])*c
->mb_penalty_factor
;
668 if(s
->quarter_sample
){
676 s
->current_picture
.motion_val
[0][s
->block_index
[block
]][0] = mx4
;
677 s
->current_picture
.motion_val
[0][s
->block_index
[block
]][1] = my4
;
679 if(mx4
!= mx
|| my4
!= my
) same
=0;
685 if (s
->mecc
.me_sub_cmp
[0] != s
->mecc
.mb_cmp
[0]) {
686 dmin_sum
+= s
->mecc
.mb_cmp
[0](s
,
687 s
->new_picture
.f
->data
[0] +
688 s
->mb_x
* 16 + s
->mb_y
* 16 * stride
,
689 c
->scratchpad
, stride
, 16);
692 if(c
->avctx
->mb_cmp
&FF_CMP_CHROMA
){
697 mx
= ff_h263_round_chroma(mx4_sum
);
698 my
= ff_h263_round_chroma(my4_sum
);
699 dxy
= ((my
& 1) << 1) | (mx
& 1);
701 offset
= (s
->mb_x
*8 + (mx
>>1)) + (s
->mb_y
*8 + (my
>>1))*s
->uvlinesize
;
704 s
->hdsp
.put_no_rnd_pixels_tab
[1][dxy
](c
->scratchpad
, s
->last_picture
.f
->data
[1] + offset
, s
->uvlinesize
, 8);
705 s
->hdsp
.put_no_rnd_pixels_tab
[1][dxy
](c
->scratchpad
+ 8, s
->last_picture
.f
->data
[2] + offset
, s
->uvlinesize
, 8);
707 s
->hdsp
.put_pixels_tab
[1][dxy
](c
->scratchpad
, s
->last_picture
.f
->data
[1] + offset
, s
->uvlinesize
, 8);
708 s
->hdsp
.put_pixels_tab
[1][dxy
](c
->scratchpad
+ 8, s
->last_picture
.f
->data
[2] + offset
, s
->uvlinesize
, 8);
711 dmin_sum
+= s
->mecc
.mb_cmp
[1](s
, s
->new_picture
.f
->data
[1] + s
->mb_x
* 8 + s
->mb_y
* 8 * s
->uvlinesize
, c
->scratchpad
, s
->uvlinesize
, 8);
712 dmin_sum
+= s
->mecc
.mb_cmp
[1](s
, s
->new_picture
.f
->data
[2] + s
->mb_x
* 8 + s
->mb_y
* 8 * s
->uvlinesize
, c
->scratchpad
+ 8, s
->uvlinesize
, 8);
718 switch(c
->avctx
->mb_cmp
&0xFF){
720 return dmin_sum+ 32*s->qscale*s->qscale;*/
724 return dmin_sum
+ 11*c
->mb_penalty_factor
;
728 static inline void init_interlaced_ref(MpegEncContext
*s
, int ref_index
){
729 MotionEstContext
* const c
= &s
->me
;
731 c
->ref
[1+ref_index
][0] = c
->ref
[0+ref_index
][0] + s
->linesize
;
732 c
->src
[1][0] = c
->src
[0][0] + s
->linesize
;
733 if(c
->flags
& FLAG_CHROMA
){
734 c
->ref
[1+ref_index
][1] = c
->ref
[0+ref_index
][1] + s
->uvlinesize
;
735 c
->ref
[1+ref_index
][2] = c
->ref
[0+ref_index
][2] + s
->uvlinesize
;
736 c
->src
[1][1] = c
->src
[0][1] + s
->uvlinesize
;
737 c
->src
[1][2] = c
->src
[0][2] + s
->uvlinesize
;
741 static int interlaced_search(MpegEncContext
*s
, int ref_index
,
742 int16_t (*mv_tables
[2][2])[2], uint8_t *field_select_tables
[2], int mx
, int my
, int user_field_select
)
744 MotionEstContext
* const c
= &s
->me
;
749 uint8_t * const mv_penalty
= c
->current_mv_penalty
;
751 const int stride
= 2*s
->linesize
;
753 const int mot_stride
= s
->mb_stride
;
754 const int xy
= s
->mb_x
+ s
->mb_y
*mot_stride
;
760 init_interlaced_ref(s
, ref_index
);
762 for(block
=0; block
<2; block
++){
764 int best_dmin
= INT_MAX
;
767 for(field_select
=0; field_select
<2; field_select
++){
768 int dmin
, mx_i
, my_i
;
769 int16_t (*mv_table
)[2]= mv_tables
[block
][field_select
];
771 if(user_field_select
){
772 av_assert1(field_select
==0 || field_select
==1);
773 av_assert1(field_select_tables
[block
][xy
]==0 || field_select_tables
[block
][xy
]==1);
774 if(field_select_tables
[block
][xy
] != field_select
)
778 P_LEFT
[0] = mv_table
[xy
- 1][0];
779 P_LEFT
[1] = mv_table
[xy
- 1][1];
780 if(P_LEFT
[0] > (c
->xmax
<<1)) P_LEFT
[0] = (c
->xmax
<<1);
782 c
->pred_x
= P_LEFT
[0];
783 c
->pred_y
= P_LEFT
[1];
785 if(!s
->first_slice_line
){
786 P_TOP
[0] = mv_table
[xy
- mot_stride
][0];
787 P_TOP
[1] = mv_table
[xy
- mot_stride
][1];
788 P_TOPRIGHT
[0] = mv_table
[xy
- mot_stride
+ 1][0];
789 P_TOPRIGHT
[1] = mv_table
[xy
- mot_stride
+ 1][1];
790 if(P_TOP
[1] > (c
->ymax
<<1)) P_TOP
[1] = (c
->ymax
<<1);
791 if(P_TOPRIGHT
[0] < (c
->xmin
<<1)) P_TOPRIGHT
[0]= (c
->xmin
<<1);
792 if(P_TOPRIGHT
[0] > (c
->xmax
<<1)) P_TOPRIGHT
[0]= (c
->xmax
<<1);
793 if(P_TOPRIGHT
[1] > (c
->ymax
<<1)) P_TOPRIGHT
[1]= (c
->ymax
<<1);
795 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
796 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
798 P_MV1
[0]= mx
; //FIXME not correct if block != field_select
801 dmin
= epzs_motion_search2(s
, &mx_i
, &my_i
, P
, block
, field_select
+ref_index
, mv_table
, (1<<16)>>1);
803 dmin
= c
->sub_motion_search(s
, &mx_i
, &my_i
, dmin
, block
, field_select
+ref_index
, size
, h
);
805 mv_table
[xy
][0]= mx_i
;
806 mv_table
[xy
][1]= my_i
;
808 if (s
->mecc
.me_sub_cmp
[0] != s
->mecc
.mb_cmp
[0]) {
812 uint8_t *ref
= c
->ref
[field_select
+ref_index
][0] + (mx_i
>>1) + (my_i
>>1)*stride
;
813 dxy
= ((my_i
& 1) << 1) | (mx_i
& 1);
816 s
->hdsp
.put_no_rnd_pixels_tab
[size
][dxy
](c
->scratchpad
, ref
, stride
, h
);
818 s
->hdsp
.put_pixels_tab
[size
][dxy
](c
->scratchpad
, ref
, stride
, h
);
820 dmin
= s
->mecc
.mb_cmp
[size
](s
, c
->src
[block
][0], c
->scratchpad
, stride
, h
);
821 dmin
+= (mv_penalty
[mx_i
-c
->pred_x
] + mv_penalty
[my_i
-c
->pred_y
] + 1)*c
->mb_penalty_factor
;
823 dmin
+= c
->mb_penalty_factor
; //field_select bits
825 dmin
+= field_select
!= block
; //slightly prefer same field
827 if(dmin
< best_dmin
){
829 best_field
= field_select
;
833 int16_t (*mv_table
)[2]= mv_tables
[block
][best_field
];
835 if(mv_table
[xy
][0] != mx
) same
=0; //FIXME check if these checks work and are any good at all
836 if(mv_table
[xy
][1]&1) same
=0;
837 if(mv_table
[xy
][1]*2 != my
) same
=0;
838 if(best_field
!= block
) same
=0;
841 field_select_tables
[block
][xy
]= best_field
;
842 dmin_sum
+= best_dmin
;
853 switch(c
->avctx
->mb_cmp
&0xFF){
855 return dmin_sum+ 32*s->qscale*s->qscale;*/
859 return dmin_sum
+ 11*c
->mb_penalty_factor
;
863 static inline int get_penalty_factor(int lambda
, int lambda2
, int type
){
867 return lambda
>>FF_LAMBDA_SHIFT
;
869 return (3*lambda
)>>(FF_LAMBDA_SHIFT
+1);
871 return (4*lambda
)>>(FF_LAMBDA_SHIFT
);
873 return (2*lambda
)>>(FF_LAMBDA_SHIFT
);
876 return (2*lambda
)>>FF_LAMBDA_SHIFT
;
881 return lambda2
>>FF_LAMBDA_SHIFT
;
887 void ff_estimate_p_frame_motion(MpegEncContext
* s
,
890 MotionEstContext
* const c
= &s
->me
;
892 int sum
, mx
, my
, dmin
;
893 int varc
; ///< the variance of the block (sum of squared (p[y][x]-average))
894 int vard
; ///< sum of squared differences with the estimated motion vector
896 const int shift
= 1+s
->quarter_sample
;
898 Picture
* const pic
= &s
->current_picture
;
900 init_ref(c
, s
->new_picture
.f
->data
, s
->last_picture
.f
->data
, NULL
, 16*mb_x
, 16*mb_y
, 0);
902 av_assert0(s
->quarter_sample
==0 || s
->quarter_sample
==1);
903 av_assert0(s
->linesize
== c
->stride
);
904 av_assert0(s
->uvlinesize
== c
->uvstride
);
906 c
->penalty_factor
= get_penalty_factor(s
->lambda
, s
->lambda2
, c
->avctx
->me_cmp
);
907 c
->sub_penalty_factor
= get_penalty_factor(s
->lambda
, s
->lambda2
, c
->avctx
->me_sub_cmp
);
908 c
->mb_penalty_factor
= get_penalty_factor(s
->lambda
, s
->lambda2
, c
->avctx
->mb_cmp
);
909 c
->current_mv_penalty
= c
->mv_penalty
[s
->f_code
] + MAX_MV
;
911 get_limits(s
, 16*mb_x
, 16*mb_y
);
914 /* intra / predictive decision */
916 sum
= s
->mpvencdsp
.pix_sum(pix
, s
->linesize
);
917 varc
= s
->mpvencdsp
.pix_norm1(pix
, s
->linesize
) -
918 (((unsigned) sum
* sum
) >> 8) + 500;
920 pic
->mb_mean
[s
->mb_stride
* mb_y
+ mb_x
] = (sum
+128)>>8;
921 pic
->mb_var
[s
->mb_stride
* mb_y
+ mb_x
] = (varc
+128)>>8;
922 c
->mb_var_sum_temp
+= (varc
+128)>>8;
924 switch(s
->me_method
) {
934 const int mot_stride
= s
->b8_stride
;
935 const int mot_xy
= s
->block_index
[0];
937 P_LEFT
[0] = s
->current_picture
.motion_val
[0][mot_xy
- 1][0];
938 P_LEFT
[1] = s
->current_picture
.motion_val
[0][mot_xy
- 1][1];
940 if(P_LEFT
[0] > (c
->xmax
<<shift
)) P_LEFT
[0] = (c
->xmax
<<shift
);
942 if(!s
->first_slice_line
) {
943 P_TOP
[0] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
][0];
944 P_TOP
[1] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
][1];
945 P_TOPRIGHT
[0] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
+ 2][0];
946 P_TOPRIGHT
[1] = s
->current_picture
.motion_val
[0][mot_xy
- mot_stride
+ 2][1];
947 if(P_TOP
[1] > (c
->ymax
<<shift
)) P_TOP
[1] = (c
->ymax
<<shift
);
948 if(P_TOPRIGHT
[0] < (c
->xmin
<<shift
)) P_TOPRIGHT
[0]= (c
->xmin
<<shift
);
949 if(P_TOPRIGHT
[1] > (c
->ymax
<<shift
)) P_TOPRIGHT
[1]= (c
->ymax
<<shift
);
951 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
952 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
954 if(s
->out_format
== FMT_H263
){
955 c
->pred_x
= P_MEDIAN
[0];
956 c
->pred_y
= P_MEDIAN
[1];
957 }else { /* mpeg1 at least */
958 c
->pred_x
= P_LEFT
[0];
959 c
->pred_y
= P_LEFT
[1];
962 c
->pred_x
= P_LEFT
[0];
963 c
->pred_y
= P_LEFT
[1];
967 dmin
= ff_epzs_motion_search(s
, &mx
, &my
, P
, 0, 0, s
->p_mv_table
, (1<<16)>>shift
, 0, 16);
972 /* At this point (mx,my) are full-pell and the relative displacement */
973 ppix
= c
->ref
[0][0] + (my
* s
->linesize
) + mx
;
975 vard
= s
->mecc
.sse
[0](NULL
, pix
, ppix
, s
->linesize
, 16);
977 pic
->mc_mb_var
[s
->mb_stride
* mb_y
+ mb_x
] = (vard
+128)>>8;
978 c
->mc_mb_var_sum_temp
+= (vard
+128)>>8;
980 if (c
->avctx
->mb_decision
> FF_MB_DECISION_SIMPLE
) {
981 int p_score
= FFMIN(vard
, varc
-500+(s
->lambda2
>>FF_LAMBDA_SHIFT
)*100);
982 int i_score
= varc
-500+(s
->lambda2
>>FF_LAMBDA_SHIFT
)*20;
983 c
->scene_change_score
+= ff_sqrt(p_score
) - ff_sqrt(i_score
);
985 if (vard
*2 + 200*256 > varc
)
986 mb_type
|= CANDIDATE_MB_TYPE_INTRA
;
987 if (varc
*2 + 200*256 > vard
|| s
->qscale
> 24){
988 // if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){
989 mb_type
|= CANDIDATE_MB_TYPE_INTER
;
990 c
->sub_motion_search(s
, &mx
, &my
, dmin
, 0, 0, 0, 16);
991 if (s
->mpv_flags
& FF_MPV_FLAG_MV0
)
993 mb_type
|= CANDIDATE_MB_TYPE_SKIPPED
; //FIXME check difference
998 if((s
->flags
&CODEC_FLAG_4MV
)
999 && !c
->skip
&& varc
>50<<8 && vard
>10<<8){
1000 if(h263_mv4_search(s
, mx
, my
, shift
) < INT_MAX
)
1001 mb_type
|=CANDIDATE_MB_TYPE_INTER4V
;
1003 set_p_mv_tables(s
, mx
, my
, 0);
1005 set_p_mv_tables(s
, mx
, my
, 1);
1006 if((s
->flags
&CODEC_FLAG_INTERLACED_ME
)
1007 && !c
->skip
){ //FIXME varc/d checks
1008 if(interlaced_search(s
, 0, s
->p_field_mv_table
, s
->p_field_select_table
, mx
, my
, 0) < INT_MAX
)
1009 mb_type
|= CANDIDATE_MB_TYPE_INTER_I
;
1013 mb_type
= CANDIDATE_MB_TYPE_INTER
;
1015 dmin
= c
->sub_motion_search(s
, &mx
, &my
, dmin
, 0, 0, 0, 16);
1016 if(c
->avctx
->me_sub_cmp
!= c
->avctx
->mb_cmp
&& !c
->skip
)
1017 dmin
= get_mb_score(s
, mx
, my
, 0, 0, 0, 16, 1);
1019 if((s
->flags
&CODEC_FLAG_4MV
)
1020 && !c
->skip
&& varc
>50<<8 && vard
>10<<8){
1021 int dmin4
= h263_mv4_search(s
, mx
, my
, shift
);
1023 mb_type
= CANDIDATE_MB_TYPE_INTER4V
;
1027 if((s
->flags
&CODEC_FLAG_INTERLACED_ME
)
1028 && !c
->skip
){ //FIXME varc/d checks
1029 int dmin_i
= interlaced_search(s
, 0, s
->p_field_mv_table
, s
->p_field_select_table
, mx
, my
, 0);
1031 mb_type
= CANDIDATE_MB_TYPE_INTER_I
;
1036 set_p_mv_tables(s
, mx
, my
, mb_type
!=CANDIDATE_MB_TYPE_INTER4V
);
1038 /* get intra luma score */
1039 if((c
->avctx
->mb_cmp
&0xFF)==FF_CMP_SSE
){
1040 intra_score
= varc
- 500;
1042 unsigned mean
= (sum
+128)>>8;
1045 for(i
=0; i
<16; i
++){
1046 *(uint32_t*)(&c
->scratchpad
[i
*s
->linesize
+ 0]) = mean
;
1047 *(uint32_t*)(&c
->scratchpad
[i
*s
->linesize
+ 4]) = mean
;
1048 *(uint32_t*)(&c
->scratchpad
[i
*s
->linesize
+ 8]) = mean
;
1049 *(uint32_t*)(&c
->scratchpad
[i
*s
->linesize
+12]) = mean
;
1052 intra_score
= s
->mecc
.mb_cmp
[0](s
, c
->scratchpad
, pix
, s
->linesize
, 16);
1054 intra_score
+= c
->mb_penalty_factor
*16;
1056 if(intra_score
< dmin
){
1057 mb_type
= CANDIDATE_MB_TYPE_INTRA
;
1058 s
->current_picture
.mb_type
[mb_y
*s
->mb_stride
+ mb_x
] = CANDIDATE_MB_TYPE_INTRA
; //FIXME cleanup
1060 s
->current_picture
.mb_type
[mb_y
*s
->mb_stride
+ mb_x
] = 0;
1063 int p_score
= FFMIN(vard
, varc
-500+(s
->lambda2
>>FF_LAMBDA_SHIFT
)*100);
1064 int i_score
= varc
-500+(s
->lambda2
>>FF_LAMBDA_SHIFT
)*20;
1065 c
->scene_change_score
+= ff_sqrt(p_score
) - ff_sqrt(i_score
);
1069 s
->mb_type
[mb_y
*s
->mb_stride
+ mb_x
]= mb_type
;
1072 int ff_pre_estimate_p_frame_motion(MpegEncContext
* s
,
1075 MotionEstContext
* const c
= &s
->me
;
1078 const int shift
= 1+s
->quarter_sample
;
1079 const int xy
= mb_x
+ mb_y
*s
->mb_stride
;
1080 init_ref(c
, s
->new_picture
.f
->data
, s
->last_picture
.f
->data
, NULL
, 16*mb_x
, 16*mb_y
, 0);
1082 av_assert0(s
->quarter_sample
==0 || s
->quarter_sample
==1);
1084 c
->pre_penalty_factor
= get_penalty_factor(s
->lambda
, s
->lambda2
, c
->avctx
->me_pre_cmp
);
1085 c
->current_mv_penalty
= c
->mv_penalty
[s
->f_code
] + MAX_MV
;
1087 get_limits(s
, 16*mb_x
, 16*mb_y
);
1090 P_LEFT
[0] = s
->p_mv_table
[xy
+ 1][0];
1091 P_LEFT
[1] = s
->p_mv_table
[xy
+ 1][1];
1093 if(P_LEFT
[0] < (c
->xmin
<<shift
)) P_LEFT
[0] = (c
->xmin
<<shift
);
1095 /* special case for first line */
1096 if (s
->first_slice_line
) {
1097 c
->pred_x
= P_LEFT
[0];
1098 c
->pred_y
= P_LEFT
[1];
1099 P_TOP
[0]= P_TOPRIGHT
[0]= P_MEDIAN
[0]=
1100 P_TOP
[1]= P_TOPRIGHT
[1]= P_MEDIAN
[1]= 0; //FIXME
1102 P_TOP
[0] = s
->p_mv_table
[xy
+ s
->mb_stride
][0];
1103 P_TOP
[1] = s
->p_mv_table
[xy
+ s
->mb_stride
][1];
1104 P_TOPRIGHT
[0] = s
->p_mv_table
[xy
+ s
->mb_stride
- 1][0];
1105 P_TOPRIGHT
[1] = s
->p_mv_table
[xy
+ s
->mb_stride
- 1][1];
1106 if(P_TOP
[1] < (c
->ymin
<<shift
)) P_TOP
[1] = (c
->ymin
<<shift
);
1107 if(P_TOPRIGHT
[0] > (c
->xmax
<<shift
)) P_TOPRIGHT
[0]= (c
->xmax
<<shift
);
1108 if(P_TOPRIGHT
[1] < (c
->ymin
<<shift
)) P_TOPRIGHT
[1]= (c
->ymin
<<shift
);
1110 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1111 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1113 c
->pred_x
= P_MEDIAN
[0];
1114 c
->pred_y
= P_MEDIAN
[1];
1117 dmin
= ff_epzs_motion_search(s
, &mx
, &my
, P
, 0, 0, s
->p_mv_table
, (1<<16)>>shift
, 0, 16);
1119 s
->p_mv_table
[xy
][0] = mx
<<shift
;
1120 s
->p_mv_table
[xy
][1] = my
<<shift
;
1125 static int estimate_motion_b(MpegEncContext
*s
, int mb_x
, int mb_y
,
1126 int16_t (*mv_table
)[2], int ref_index
, int f_code
)
1128 MotionEstContext
* const c
= &s
->me
;
1131 const int shift
= 1+s
->quarter_sample
;
1132 const int mot_stride
= s
->mb_stride
;
1133 const int mot_xy
= mb_y
*mot_stride
+ mb_x
;
1134 uint8_t * const mv_penalty
= c
->mv_penalty
[f_code
] + MAX_MV
;
1137 c
->penalty_factor
= get_penalty_factor(s
->lambda
, s
->lambda2
, c
->avctx
->me_cmp
);
1138 c
->sub_penalty_factor
= get_penalty_factor(s
->lambda
, s
->lambda2
, c
->avctx
->me_sub_cmp
);
1139 c
->mb_penalty_factor
= get_penalty_factor(s
->lambda
, s
->lambda2
, c
->avctx
->mb_cmp
);
1140 c
->current_mv_penalty
= mv_penalty
;
1142 get_limits(s
, 16*mb_x
, 16*mb_y
);
1144 switch(s
->me_method
) {
1153 P_LEFT
[0] = mv_table
[mot_xy
- 1][0];
1154 P_LEFT
[1] = mv_table
[mot_xy
- 1][1];
1156 if (P_LEFT
[0] > (c
->xmax
<< shift
)) P_LEFT
[0] = (c
->xmax
<< shift
);
1158 /* special case for first line */
1159 if (!s
->first_slice_line
) {
1160 P_TOP
[0] = mv_table
[mot_xy
- mot_stride
][0];
1161 P_TOP
[1] = mv_table
[mot_xy
- mot_stride
][1];
1162 P_TOPRIGHT
[0] = mv_table
[mot_xy
- mot_stride
+ 1][0];
1163 P_TOPRIGHT
[1] = mv_table
[mot_xy
- mot_stride
+ 1][1];
1164 if (P_TOP
[1] > (c
->ymax
<< shift
)) P_TOP
[1] = (c
->ymax
<< shift
);
1165 if (P_TOPRIGHT
[0] < (c
->xmin
<< shift
)) P_TOPRIGHT
[0] = (c
->xmin
<< shift
);
1166 if (P_TOPRIGHT
[1] > (c
->ymax
<< shift
)) P_TOPRIGHT
[1] = (c
->ymax
<< shift
);
1168 P_MEDIAN
[0] = mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1169 P_MEDIAN
[1] = mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1171 c
->pred_x
= P_LEFT
[0];
1172 c
->pred_y
= P_LEFT
[1];
1174 if(mv_table
== s
->b_forw_mv_table
){
1175 mv_scale
= (s
->pb_time
<<16) / (s
->pp_time
<<shift
);
1177 mv_scale
= ((s
->pb_time
- s
->pp_time
)<<16) / (s
->pp_time
<<shift
);
1180 dmin
= ff_epzs_motion_search(s
, &mx
, &my
, P
, 0, ref_index
, s
->p_mv_table
, mv_scale
, 0, 16);
1185 dmin
= c
->sub_motion_search(s
, &mx
, &my
, dmin
, 0, ref_index
, 0, 16);
1187 if(c
->avctx
->me_sub_cmp
!= c
->avctx
->mb_cmp
&& !c
->skip
)
1188 dmin
= get_mb_score(s
, mx
, my
, 0, ref_index
, 0, 16, 1);
1190 // s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
1191 mv_table
[mot_xy
][0]= mx
;
1192 mv_table
[mot_xy
][1]= my
;
1197 static inline int check_bidir_mv(MpegEncContext
* s
,
1198 int motion_fx
, int motion_fy
,
1199 int motion_bx
, int motion_by
,
1200 int pred_fx
, int pred_fy
,
1201 int pred_bx
, int pred_by
,
1205 //FIXME better f_code prediction (max mv & distance)
1207 MotionEstContext
* const c
= &s
->me
;
1208 uint8_t * const mv_penalty_f
= c
->mv_penalty
[s
->f_code
] + MAX_MV
; // f_code of the prev frame
1209 uint8_t * const mv_penalty_b
= c
->mv_penalty
[s
->b_code
] + MAX_MV
; // f_code of the prev frame
1210 int stride
= c
->stride
;
1211 uint8_t *dest_y
= c
->scratchpad
;
1216 uint8_t **src_data
= c
->src
[0];
1217 uint8_t **ref_data
= c
->ref
[0];
1218 uint8_t **ref2_data
= c
->ref
[2];
1220 if(s
->quarter_sample
){
1221 dxy
= ((motion_fy
& 3) << 2) | (motion_fx
& 3);
1222 src_x
= motion_fx
>> 2;
1223 src_y
= motion_fy
>> 2;
1225 ptr
= ref_data
[0] + (src_y
* stride
) + src_x
;
1226 s
->qdsp
.put_qpel_pixels_tab
[0][dxy
](dest_y
, ptr
, stride
);
1228 dxy
= ((motion_by
& 3) << 2) | (motion_bx
& 3);
1229 src_x
= motion_bx
>> 2;
1230 src_y
= motion_by
>> 2;
1232 ptr
= ref2_data
[0] + (src_y
* stride
) + src_x
;
1233 s
->qdsp
.avg_qpel_pixels_tab
[size
][dxy
](dest_y
, ptr
, stride
);
1235 dxy
= ((motion_fy
& 1) << 1) | (motion_fx
& 1);
1236 src_x
= motion_fx
>> 1;
1237 src_y
= motion_fy
>> 1;
1239 ptr
= ref_data
[0] + (src_y
* stride
) + src_x
;
1240 s
->hdsp
.put_pixels_tab
[size
][dxy
](dest_y
, ptr
, stride
, h
);
1242 dxy
= ((motion_by
& 1) << 1) | (motion_bx
& 1);
1243 src_x
= motion_bx
>> 1;
1244 src_y
= motion_by
>> 1;
1246 ptr
= ref2_data
[0] + (src_y
* stride
) + src_x
;
1247 s
->hdsp
.avg_pixels_tab
[size
][dxy
](dest_y
, ptr
, stride
, h
);
1250 fbmin
= (mv_penalty_f
[motion_fx
-pred_fx
] + mv_penalty_f
[motion_fy
-pred_fy
])*c
->mb_penalty_factor
1251 +(mv_penalty_b
[motion_bx
-pred_bx
] + mv_penalty_b
[motion_by
-pred_by
])*c
->mb_penalty_factor
1252 + s
->mecc
.mb_cmp
[size
](s
, src_data
[0], dest_y
, stride
, h
); // FIXME new_pic
1254 if(c
->avctx
->mb_cmp
&FF_CMP_CHROMA
){
1261 /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1262 static inline int bidir_refine(MpegEncContext
* s
, int mb_x
, int mb_y
)
1264 MotionEstContext
* const c
= &s
->me
;
1265 const int mot_stride
= s
->mb_stride
;
1266 const int xy
= mb_y
*mot_stride
+ mb_x
;
1268 int pred_fx
= s
->b_bidir_forw_mv_table
[xy
-1][0];
1269 int pred_fy
= s
->b_bidir_forw_mv_table
[xy
-1][1];
1270 int pred_bx
= s
->b_bidir_back_mv_table
[xy
-1][0];
1271 int pred_by
= s
->b_bidir_back_mv_table
[xy
-1][1];
1272 int motion_fx
= s
->b_bidir_forw_mv_table
[xy
][0]= s
->b_forw_mv_table
[xy
][0];
1273 int motion_fy
= s
->b_bidir_forw_mv_table
[xy
][1]= s
->b_forw_mv_table
[xy
][1];
1274 int motion_bx
= s
->b_bidir_back_mv_table
[xy
][0]= s
->b_back_mv_table
[xy
][0];
1275 int motion_by
= s
->b_bidir_back_mv_table
[xy
][1]= s
->b_back_mv_table
[xy
][1];
1276 const int flags
= c
->sub_flags
;
1277 const int qpel
= flags
&FLAG_QPEL
;
1278 const int shift
= 1+qpel
;
1279 const int xmin
= c
->xmin
<<shift
;
1280 const int ymin
= c
->ymin
<<shift
;
1281 const int xmax
= c
->xmax
<<shift
;
1282 const int ymax
= c
->ymax
<<shift
;
1283 #define HASH(fx,fy,bx,by) ((fx)+17*(fy)+63*(bx)+117*(by))
1284 #define HASH8(fx,fy,bx,by) ((uint8_t)HASH(fx,fy,bx,by))
1285 int hashidx
= HASH(motion_fx
,motion_fy
, motion_bx
, motion_by
);
1286 uint8_t map
[256] = { 0 };
1288 map
[hashidx
&255] = 1;
1290 fbmin
= check_bidir_mv(s
, motion_fx
, motion_fy
,
1291 motion_bx
, motion_by
,
1296 if(s
->avctx
->bidir_refine
){
1298 static const uint8_t limittab
[5]={0,8,32,64,80};
1299 const int limit
= limittab
[s
->avctx
->bidir_refine
];
1300 static const int8_t vect
[][4]={
1301 { 0, 0, 0, 1}, { 0, 0, 0,-1}, { 0, 0, 1, 0}, { 0, 0,-1, 0}, { 0, 1, 0, 0}, { 0,-1, 0, 0}, { 1, 0, 0, 0}, {-1, 0, 0, 0},
1303 { 0, 0, 1, 1}, { 0, 0,-1,-1}, { 0, 1, 1, 0}, { 0,-1,-1, 0}, { 1, 1, 0, 0}, {-1,-1, 0, 0}, { 1, 0, 0, 1}, {-1, 0, 0,-1},
1304 { 0, 1, 0, 1}, { 0,-1, 0,-1}, { 1, 0, 1, 0}, {-1, 0,-1, 0},
1305 { 0, 0,-1, 1}, { 0, 0, 1,-1}, { 0,-1, 1, 0}, { 0, 1,-1, 0}, {-1, 1, 0, 0}, { 1,-1, 0, 0}, { 1, 0, 0,-1}, {-1, 0, 0, 1},
1306 { 0,-1, 0, 1}, { 0, 1, 0,-1}, {-1, 0, 1, 0}, { 1, 0,-1, 0},
1308 { 0, 1, 1, 1}, { 0,-1,-1,-1}, { 1, 1, 1, 0}, {-1,-1,-1, 0}, { 1, 1, 0, 1}, {-1,-1, 0,-1}, { 1, 0, 1, 1}, {-1, 0,-1,-1},
1309 { 0,-1, 1, 1}, { 0, 1,-1,-1}, {-1, 1, 1, 0}, { 1,-1,-1, 0}, { 1, 1, 0,-1}, {-1,-1, 0, 1}, { 1, 0,-1, 1}, {-1, 0, 1,-1},
1310 { 0, 1,-1, 1}, { 0,-1, 1,-1}, { 1,-1, 1, 0}, {-1, 1,-1, 0}, {-1, 1, 0, 1}, { 1,-1, 0,-1}, { 1, 0, 1,-1}, {-1, 0,-1, 1},
1311 { 0, 1, 1,-1}, { 0,-1,-1, 1}, { 1, 1,-1, 0}, {-1,-1, 1, 0}, { 1,-1, 0, 1}, {-1, 1, 0,-1}, {-1, 0, 1, 1}, { 1, 0,-1,-1},
1313 { 1, 1, 1, 1}, {-1,-1,-1,-1},
1314 { 1, 1, 1,-1}, {-1,-1,-1, 1}, { 1, 1,-1, 1}, {-1,-1, 1,-1}, { 1,-1, 1, 1}, {-1, 1,-1,-1}, {-1, 1, 1, 1}, { 1,-1,-1,-1},
1315 { 1, 1,-1,-1}, {-1,-1, 1, 1}, { 1,-1,-1, 1}, {-1, 1, 1,-1}, { 1,-1, 1,-1}, {-1, 1,-1, 1},
1317 static const uint8_t hash
[]={
1318 HASH8( 0, 0, 0, 1), HASH8( 0, 0, 0,-1), HASH8( 0, 0, 1, 0), HASH8( 0, 0,-1, 0), HASH8( 0, 1, 0, 0), HASH8( 0,-1, 0, 0), HASH8( 1, 0, 0, 0), HASH8(-1, 0, 0, 0),
1320 HASH8( 0, 0, 1, 1), HASH8( 0, 0,-1,-1), HASH8( 0, 1, 1, 0), HASH8( 0,-1,-1, 0), HASH8( 1, 1, 0, 0), HASH8(-1,-1, 0, 0), HASH8( 1, 0, 0, 1), HASH8(-1, 0, 0,-1),
1321 HASH8( 0, 1, 0, 1), HASH8( 0,-1, 0,-1), HASH8( 1, 0, 1, 0), HASH8(-1, 0,-1, 0),
1322 HASH8( 0, 0,-1, 1), HASH8( 0, 0, 1,-1), HASH8( 0,-1, 1, 0), HASH8( 0, 1,-1, 0), HASH8(-1, 1, 0, 0), HASH8( 1,-1, 0, 0), HASH8( 1, 0, 0,-1), HASH8(-1, 0, 0, 1),
1323 HASH8( 0,-1, 0, 1), HASH8( 0, 1, 0,-1), HASH8(-1, 0, 1, 0), HASH8( 1, 0,-1, 0),
1325 HASH8( 0, 1, 1, 1), HASH8( 0,-1,-1,-1), HASH8( 1, 1, 1, 0), HASH8(-1,-1,-1, 0), HASH8( 1, 1, 0, 1), HASH8(-1,-1, 0,-1), HASH8( 1, 0, 1, 1), HASH8(-1, 0,-1,-1),
1326 HASH8( 0,-1, 1, 1), HASH8( 0, 1,-1,-1), HASH8(-1, 1, 1, 0), HASH8( 1,-1,-1, 0), HASH8( 1, 1, 0,-1), HASH8(-1,-1, 0, 1), HASH8( 1, 0,-1, 1), HASH8(-1, 0, 1,-1),
1327 HASH8( 0, 1,-1, 1), HASH8( 0,-1, 1,-1), HASH8( 1,-1, 1, 0), HASH8(-1, 1,-1, 0), HASH8(-1, 1, 0, 1), HASH8( 1,-1, 0,-1), HASH8( 1, 0, 1,-1), HASH8(-1, 0,-1, 1),
1328 HASH8( 0, 1, 1,-1), HASH8( 0,-1,-1, 1), HASH8( 1, 1,-1, 0), HASH8(-1,-1, 1, 0), HASH8( 1,-1, 0, 1), HASH8(-1, 1, 0,-1), HASH8(-1, 0, 1, 1), HASH8( 1, 0,-1,-1),
1330 HASH8( 1, 1, 1, 1), HASH8(-1,-1,-1,-1),
1331 HASH8( 1, 1, 1,-1), HASH8(-1,-1,-1, 1), HASH8( 1, 1,-1, 1), HASH8(-1,-1, 1,-1), HASH8( 1,-1, 1, 1), HASH8(-1, 1,-1,-1), HASH8(-1, 1, 1, 1), HASH8( 1,-1,-1,-1),
1332 HASH8( 1, 1,-1,-1), HASH8(-1,-1, 1, 1), HASH8( 1,-1,-1, 1), HASH8(-1, 1, 1,-1), HASH8( 1,-1, 1,-1), HASH8(-1, 1,-1, 1),
1335 #define CHECK_BIDIR(fx,fy,bx,by)\
1336 if( !map[(hashidx+HASH(fx,fy,bx,by))&255]\
1337 &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\
1338 &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\
1340 map[(hashidx+HASH(fx,fy,bx,by))&255] = 1;\
1341 score= check_bidir_mv(s, motion_fx+fx, motion_fy+fy, motion_bx+bx, motion_by+by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);\
1343 hashidx += HASH(fx,fy,bx,by);\
1352 #define CHECK_BIDIR2(a,b,c,d)\
1353 CHECK_BIDIR(a,b,c,d)\
1354 CHECK_BIDIR(-(a),-(b),-(c),-(d))
1361 CHECK_BIDIR2(0,0,0,1)
1362 CHECK_BIDIR2(0,0,1,0)
1363 CHECK_BIDIR2(0,1,0,0)
1364 CHECK_BIDIR2(1,0,0,0)
1366 for(i
=8; i
<limit
; i
++){
1367 int fx
= motion_fx
+vect
[i
][0];
1368 int fy
= motion_fy
+vect
[i
][1];
1369 int bx
= motion_bx
+vect
[i
][2];
1370 int by
= motion_by
+vect
[i
][3];
1372 int a
= (xmax
- FFMAX(fx
,bx
))|(FFMIN(fx
,bx
) - xmin
);
1373 int b
= (ymax
- FFMAX(fy
,by
))|(FFMIN(fy
,by
) - ymin
);
1375 map
[(hashidx
+hash
[i
])&255] = 1;
1377 if(!map
[(hashidx
+hash
[i
])&255]){
1379 map
[(hashidx
+hash
[i
])&255] = 1;
1380 score
= check_bidir_mv(s
, fx
, fy
, bx
, by
, pred_fx
, pred_fy
, pred_bx
, pred_by
, 0, 16);
1391 int a
= FFMIN(xmax
- FFMAX(fx
,bx
), FFMIN(fx
,bx
) - xmin
);
1392 int b
= FFMIN(ymax
- FFMAX(fy
,by
), FFMIN(fy
,by
) - ymin
);
1393 borderdist
= FFMIN(a
,b
);
1401 s
->b_bidir_forw_mv_table
[xy
][0]= motion_fx
;
1402 s
->b_bidir_forw_mv_table
[xy
][1]= motion_fy
;
1403 s
->b_bidir_back_mv_table
[xy
][0]= motion_bx
;
1404 s
->b_bidir_back_mv_table
[xy
][1]= motion_by
;
1409 static inline int direct_search(MpegEncContext
* s
, int mb_x
, int mb_y
)
1411 MotionEstContext
* const c
= &s
->me
;
1413 const int mot_stride
= s
->mb_stride
;
1414 const int mot_xy
= mb_y
*mot_stride
+ mb_x
;
1415 const int shift
= 1+s
->quarter_sample
;
1417 const int time_pp
= s
->pp_time
;
1418 const int time_pb
= s
->pb_time
;
1419 int mx
, my
, xmin
, xmax
, ymin
, ymax
;
1420 int16_t (*mv_table
)[2]= s
->b_direct_mv_table
;
1422 c
->current_mv_penalty
= c
->mv_penalty
[1] + MAX_MV
;
1423 ymin
= xmin
=(-32)>>shift
;
1424 ymax
= xmax
= 31>>shift
;
1426 if (IS_8X8(s
->next_picture
.mb_type
[mot_xy
])) {
1427 s
->mv_type
= MV_TYPE_8X8
;
1429 s
->mv_type
= MV_TYPE_16X16
;
1433 int index
= s
->block_index
[i
];
1436 c
->co_located_mv
[i
][0] = s
->next_picture
.motion_val
[0][index
][0];
1437 c
->co_located_mv
[i
][1] = s
->next_picture
.motion_val
[0][index
][1];
1438 c
->direct_basis_mv
[i
][0]= c
->co_located_mv
[i
][0]*time_pb
/time_pp
+ ((i
& 1)<<(shift
+3));
1439 c
->direct_basis_mv
[i
][1]= c
->co_located_mv
[i
][1]*time_pb
/time_pp
+ ((i
>>1)<<(shift
+3));
1440 // c->direct_basis_mv[1][i][0]= c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
1441 // c->direct_basis_mv[1][i][1]= c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);
1443 max
= FFMAX(c
->direct_basis_mv
[i
][0], c
->direct_basis_mv
[i
][0] - c
->co_located_mv
[i
][0])>>shift
;
1444 min
= FFMIN(c
->direct_basis_mv
[i
][0], c
->direct_basis_mv
[i
][0] - c
->co_located_mv
[i
][0])>>shift
;
1445 max
+= 16*mb_x
+ 1; // +-1 is for the simpler rounding
1447 xmax
= FFMIN(xmax
, s
->width
- max
);
1448 xmin
= FFMAX(xmin
, - 16 - min
);
1450 max
= FFMAX(c
->direct_basis_mv
[i
][1], c
->direct_basis_mv
[i
][1] - c
->co_located_mv
[i
][1])>>shift
;
1451 min
= FFMIN(c
->direct_basis_mv
[i
][1], c
->direct_basis_mv
[i
][1] - c
->co_located_mv
[i
][1])>>shift
;
1452 max
+= 16*mb_y
+ 1; // +-1 is for the simpler rounding
1454 ymax
= FFMIN(ymax
, s
->height
- max
);
1455 ymin
= FFMAX(ymin
, - 16 - min
);
1457 if(s
->mv_type
== MV_TYPE_16X16
) break;
1460 av_assert2(xmax
<= 15 && ymax
<= 15 && xmin
>= -16 && ymin
>= -16);
1462 if(xmax
< 0 || xmin
>0 || ymax
< 0 || ymin
> 0){
1463 s
->b_direct_mv_table
[mot_xy
][0]= 0;
1464 s
->b_direct_mv_table
[mot_xy
][1]= 0;
1466 return 256*256*256*64;
1473 c
->flags
|= FLAG_DIRECT
;
1474 c
->sub_flags
|= FLAG_DIRECT
;
1478 P_LEFT
[0] = av_clip(mv_table
[mot_xy
- 1][0], xmin
<<shift
, xmax
<<shift
);
1479 P_LEFT
[1] = av_clip(mv_table
[mot_xy
- 1][1], ymin
<<shift
, ymax
<<shift
);
1481 /* special case for first line */
1482 if (!s
->first_slice_line
) { //FIXME maybe allow this over thread boundary as it is clipped
1483 P_TOP
[0] = av_clip(mv_table
[mot_xy
- mot_stride
][0], xmin
<<shift
, xmax
<<shift
);
1484 P_TOP
[1] = av_clip(mv_table
[mot_xy
- mot_stride
][1], ymin
<<shift
, ymax
<<shift
);
1485 P_TOPRIGHT
[0] = av_clip(mv_table
[mot_xy
- mot_stride
+ 1 ][0], xmin
<<shift
, xmax
<<shift
);
1486 P_TOPRIGHT
[1] = av_clip(mv_table
[mot_xy
- mot_stride
+ 1 ][1], ymin
<<shift
, ymax
<<shift
);
1488 P_MEDIAN
[0]= mid_pred(P_LEFT
[0], P_TOP
[0], P_TOPRIGHT
[0]);
1489 P_MEDIAN
[1]= mid_pred(P_LEFT
[1], P_TOP
[1], P_TOPRIGHT
[1]);
1492 dmin
= ff_epzs_motion_search(s
, &mx
, &my
, P
, 0, 0, mv_table
, 1<<(16-shift
), 0, 16);
1493 if(c
->sub_flags
&FLAG_QPEL
)
1494 dmin
= qpel_motion_search(s
, &mx
, &my
, dmin
, 0, 0, 0, 16);
1496 dmin
= hpel_motion_search(s
, &mx
, &my
, dmin
, 0, 0, 0, 16);
1498 if(c
->avctx
->me_sub_cmp
!= c
->avctx
->mb_cmp
&& !c
->skip
)
1499 dmin
= get_mb_score(s
, mx
, my
, 0, 0, 0, 16, 1);
1501 get_limits(s
, 16*mb_x
, 16*mb_y
); //restore c->?min/max, maybe not needed
1503 mv_table
[mot_xy
][0]= mx
;
1504 mv_table
[mot_xy
][1]= my
;
1505 c
->flags
&= ~FLAG_DIRECT
;
1506 c
->sub_flags
&= ~FLAG_DIRECT
;
1511 void ff_estimate_b_frame_motion(MpegEncContext
* s
,
1514 MotionEstContext
* const c
= &s
->me
;
1515 const int penalty_factor
= c
->mb_penalty_factor
;
1516 int fmin
, bmin
, dmin
, fbmin
, bimin
, fimin
;
1518 const int xy
= mb_y
*s
->mb_stride
+ mb_x
;
1519 init_ref(c
, s
->new_picture
.f
->data
, s
->last_picture
.f
->data
,
1520 s
->next_picture
.f
->data
, 16 * mb_x
, 16 * mb_y
, 2);
1522 get_limits(s
, 16*mb_x
, 16*mb_y
);
1526 if (s
->codec_id
== AV_CODEC_ID_MPEG4
&& s
->next_picture
.mbskip_table
[xy
]) {
1527 int score
= direct_search(s
, mb_x
, mb_y
); //FIXME just check 0,0
1529 score
= ((unsigned)(score
*score
+ 128*256))>>16;
1530 c
->mc_mb_var_sum_temp
+= score
;
1531 s
->current_picture
.mc_mb_var
[mb_y
*s
->mb_stride
+ mb_x
] = score
; //FIXME use SSE
1532 s
->mb_type
[mb_y
*s
->mb_stride
+ mb_x
]= CANDIDATE_MB_TYPE_DIRECT0
;
1537 if (s
->codec_id
== AV_CODEC_ID_MPEG4
)
1538 dmin
= direct_search(s
, mb_x
, mb_y
);
1541 //FIXME penalty stuff for non mpeg4
1543 fmin
= estimate_motion_b(s
, mb_x
, mb_y
, s
->b_forw_mv_table
, 0, s
->f_code
) +
1547 bmin
= estimate_motion_b(s
, mb_x
, mb_y
, s
->b_back_mv_table
, 2, s
->b_code
) +
1549 av_dlog(s
, " %d %d ", s
->b_forw_mv_table
[xy
][0], s
->b_forw_mv_table
[xy
][1]);
1552 fbmin
= bidir_refine(s
, mb_x
, mb_y
) + penalty_factor
;
1553 av_dlog(s
, "%d %d %d %d\n", dmin
, fmin
, bmin
, fbmin
);
1555 if(s
->flags
& CODEC_FLAG_INTERLACED_ME
){
1556 //FIXME mb type penalty
1558 c
->current_mv_penalty
= c
->mv_penalty
[s
->f_code
] + MAX_MV
;
1559 fimin
= interlaced_search(s
, 0,
1560 s
->b_field_mv_table
[0], s
->b_field_select_table
[0],
1561 s
->b_forw_mv_table
[xy
][0], s
->b_forw_mv_table
[xy
][1], 0);
1562 c
->current_mv_penalty
= c
->mv_penalty
[s
->b_code
] + MAX_MV
;
1563 bimin
= interlaced_search(s
, 2,
1564 s
->b_field_mv_table
[1], s
->b_field_select_table
[1],
1565 s
->b_back_mv_table
[xy
][0], s
->b_back_mv_table
[xy
][1], 0);
1567 fimin
= bimin
= INT_MAX
;
1571 type
= CANDIDATE_MB_TYPE_FORWARD
;
1575 type
= CANDIDATE_MB_TYPE_DIRECT
;
1579 type
= CANDIDATE_MB_TYPE_BACKWARD
;
1583 type
= CANDIDATE_MB_TYPE_BIDIR
;
1587 type
= CANDIDATE_MB_TYPE_FORWARD_I
;
1591 type
= CANDIDATE_MB_TYPE_BACKWARD_I
;
1594 score
= ((unsigned)(score
*score
+ 128*256))>>16;
1595 c
->mc_mb_var_sum_temp
+= score
;
1596 s
->current_picture
.mc_mb_var
[mb_y
*s
->mb_stride
+ mb_x
] = score
; //FIXME use SSE
1599 if(c
->avctx
->mb_decision
> FF_MB_DECISION_SIMPLE
){
1600 type
= CANDIDATE_MB_TYPE_FORWARD
| CANDIDATE_MB_TYPE_BACKWARD
| CANDIDATE_MB_TYPE_BIDIR
| CANDIDATE_MB_TYPE_DIRECT
;
1602 type
|= CANDIDATE_MB_TYPE_FORWARD_I
;
1604 type
|= CANDIDATE_MB_TYPE_BACKWARD_I
;
1605 if(fimin
< INT_MAX
&& bimin
< INT_MAX
){
1606 type
|= CANDIDATE_MB_TYPE_BIDIR_I
;
1608 //FIXME something smarter
1609 if(dmin
>256*256*16) type
&= ~CANDIDATE_MB_TYPE_DIRECT
; //do not try direct mode if it is invalid for this MB
1610 if (s
->codec_id
== AV_CODEC_ID_MPEG4
&& type
&CANDIDATE_MB_TYPE_DIRECT
&&
1611 s
->mpv_flags
& FF_MPV_FLAG_MV0
&& *(uint32_t*)s
->b_direct_mv_table
[xy
])
1612 type
|= CANDIDATE_MB_TYPE_DIRECT0
;
1615 s
->mb_type
[mb_y
*s
->mb_stride
+ mb_x
]= type
;
1618 /* find best f_code for ME which do unlimited searches */
1619 int ff_get_best_fcode(MpegEncContext
* s
, int16_t (*mv_table
)[2], int type
)
1621 if(s
->me_method
>=ME_EPZS
){
1623 int i
, y
, range
= s
->avctx
->me_range
? s
->avctx
->me_range
: (INT_MAX
/2);
1624 uint8_t * fcode_tab
= s
->fcode_tab
;
1626 int best_score
=-10000000;
1628 if(s
->msmpeg4_version
)
1629 range
= FFMIN(range
, 16);
1630 else if(s
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
&& s
->avctx
->strict_std_compliance
>= FF_COMPLIANCE_NORMAL
)
1631 range
= FFMIN(range
, 256);
1633 for(i
=0; i
<8; i
++) score
[i
]= s
->mb_num
*(8-i
);
1635 for(y
=0; y
<s
->mb_height
; y
++){
1637 int xy
= y
*s
->mb_stride
;
1638 for(x
=0; x
<s
->mb_width
; x
++){
1639 if(s
->mb_type
[xy
] & type
){
1640 int mx
= mv_table
[xy
][0];
1641 int my
= mv_table
[xy
][1];
1642 int fcode
= FFMAX(fcode_tab
[mx
+ MAX_MV
],
1643 fcode_tab
[my
+ MAX_MV
]);
1646 if(mx
>= range
|| mx
< -range
||
1647 my
>= range
|| my
< -range
)
1650 for(j
=0; j
<fcode
&& j
<8; j
++){
1651 if(s
->pict_type
==AV_PICTURE_TYPE_B
|| s
->current_picture
.mc_mb_var
[xy
] < s
->current_picture
.mb_var
[xy
])
1660 if(score
[i
] > best_score
){
1661 best_score
= score
[i
];
1672 void ff_fix_long_p_mvs(MpegEncContext
* s
)
1674 MotionEstContext
* const c
= &s
->me
;
1675 const int f_code
= s
->f_code
;
1677 av_assert0(s
->pict_type
==AV_PICTURE_TYPE_P
);
1679 range
= (((s
->out_format
== FMT_MPEG1
|| s
->msmpeg4_version
) ? 8 : 16) << f_code
);
1681 av_assert0(range
<= 16 || !s
->msmpeg4_version
);
1682 av_assert0(range
<=256 || !(s
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
&& s
->avctx
->strict_std_compliance
>= FF_COMPLIANCE_NORMAL
));
1684 if(c
->avctx
->me_range
&& range
> c
->avctx
->me_range
) range
= c
->avctx
->me_range
;
1686 if(s
->flags
&CODEC_FLAG_4MV
){
1687 const int wrap
= s
->b8_stride
;
1689 /* clip / convert to intra 8x8 type MVs */
1690 for(y
=0; y
<s
->mb_height
; y
++){
1692 int i
= y
*s
->mb_stride
;
1695 for(x
=0; x
<s
->mb_width
; x
++){
1696 if(s
->mb_type
[i
]&CANDIDATE_MB_TYPE_INTER4V
){
1698 for(block
=0; block
<4; block
++){
1699 int off
= (block
& 1) + (block
>>1)*wrap
;
1700 int mx
= s
->current_picture
.motion_val
[0][ xy
+ off
][0];
1701 int my
= s
->current_picture
.motion_val
[0][ xy
+ off
][1];
1703 if( mx
>=range
|| mx
<-range
1704 || my
>=range
|| my
<-range
){
1705 s
->mb_type
[i
] &= ~CANDIDATE_MB_TYPE_INTER4V
;
1706 s
->mb_type
[i
] |= CANDIDATE_MB_TYPE_INTRA
;
1707 s
->current_picture
.mb_type
[i
] = CANDIDATE_MB_TYPE_INTRA
;
1720 * @param truncate 1 for truncation, 0 for using intra
1722 void ff_fix_long_mvs(MpegEncContext
* s
, uint8_t *field_select_table
, int field_select
,
1723 int16_t (*mv_table
)[2], int f_code
, int type
, int truncate
)
1725 MotionEstContext
* const c
= &s
->me
;
1726 int y
, h_range
, v_range
;
1728 // RAL: 8 in MPEG-1, 16 in MPEG-4
1729 int range
= (((s
->out_format
== FMT_MPEG1
|| s
->msmpeg4_version
) ? 8 : 16) << f_code
);
1731 if(c
->avctx
->me_range
&& range
> c
->avctx
->me_range
) range
= c
->avctx
->me_range
;
1734 v_range
= field_select_table
? range
>>1 : range
;
1736 /* clip / convert to intra 16x16 type MVs */
1737 for(y
=0; y
<s
->mb_height
; y
++){
1739 int xy
= y
*s
->mb_stride
;
1740 for(x
=0; x
<s
->mb_width
; x
++){
1741 if (s
->mb_type
[xy
] & type
){ // RAL: "type" test added...
1742 if (!field_select_table
|| field_select_table
[xy
] == field_select
) {
1743 if( mv_table
[xy
][0] >=h_range
|| mv_table
[xy
][0] <-h_range
1744 || mv_table
[xy
][1] >=v_range
|| mv_table
[xy
][1] <-v_range
){
1747 if (mv_table
[xy
][0] > h_range
-1) mv_table
[xy
][0]= h_range
-1;
1748 else if(mv_table
[xy
][0] < -h_range
) mv_table
[xy
][0]= -h_range
;
1749 if (mv_table
[xy
][1] > v_range
-1) mv_table
[xy
][1]= v_range
-1;
1750 else if(mv_table
[xy
][1] < -v_range
) mv_table
[xy
][1]= -v_range
;
1752 s
->mb_type
[xy
] &= ~type
;
1753 s
->mb_type
[xy
] |= CANDIDATE_MB_TYPE_INTRA
;