FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
motion_est.c
Go to the documentation of this file.
1 /*
2  * Motion estimation
3  * Copyright (c) 2000,2001 Fabrice Bellard
4  * Copyright (c) 2002-2004 Michael Niedermayer
5  *
6  * new motion estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
7  *
8  * This file is part of FFmpeg.
9  *
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.
14  *
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.
19  *
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
23  */
24 
25 /**
26  * @file
27  * Motion estimation.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <limits.h>
33 
34 #include "avcodec.h"
35 #include "h263.h"
36 #include "mathops.h"
37 #include "motion_est.h"
38 #include "mpegutils.h"
39 #include "mpegvideoenc.h"
40 
41 #define P_LEFT P[1]
42 #define P_TOP P[2]
43 #define P_TOPRIGHT P[3]
44 #define P_MEDIAN P[4]
45 #define P_MV1 P[9]
46 
47 #define ME_MAP_SHIFT 3
48 #define ME_MAP_MV_BITS 11
49 
50 static int sad_hpel_motion_search(MPVEncContext *const s,
51  int *mx_ptr, int *my_ptr, int dmin,
52  int src_index, int ref_index,
53  int size, int h);
54 
55 static inline unsigned update_map_generation(MotionEstContext *c)
56 {
57  c->map_generation+= 1<<(ME_MAP_MV_BITS*2);
58  if(c->map_generation==0){
59  c->map_generation= 1<<(ME_MAP_MV_BITS*2);
60  memset(c->map, 0, sizeof(uint32_t)*ME_MAP_SIZE);
61  }
62  return c->map_generation;
63 }
64 
65 /* shape adaptive search stuff */
66 typedef struct Minima{
67  int height;
68  int x, y;
69  int checked;
70 }Minima;
71 
72 static int minima_cmp(const void *a, const void *b){
73  const Minima *da = (const Minima *) a;
74  const Minima *db = (const Minima *) b;
75 
76  return da->height - db->height;
77 }
78 
79 #define FLAG_QPEL 1 //must be 1
80 #define FLAG_CHROMA 2
81 #define FLAG_DIRECT 4
82 
83 static inline void init_ref(MotionEstContext *c, uint8_t *const src[3],
84  uint8_t *const ref[3], uint8_t *const ref2[3],
85  int x, int y, int ref_index)
86 {
87  const int offset[3]= {
88  y*c-> stride + x,
89  ((y*c->uvstride + x)>>1),
90  ((y*c->uvstride + x)>>1),
91  };
92  int i;
93  for(i=0; i<3; i++){
94  c->src[0][i]= src [i] + offset[i];
95  c->ref[0][i]= ref [i] + offset[i];
96  }
97  if(ref_index){
98  for(i=0; i<3; i++){
99  c->ref[ref_index][i]= ref2[i] + offset[i];
100  }
101  }
102 }
103 
104 static int get_flags(MotionEstContext *c, int direct, int chroma){
105  return ((c->avctx->flags&AV_CODEC_FLAG_QPEL) ? FLAG_QPEL : 0)
106  + (direct ? FLAG_DIRECT : 0)
107  + (chroma ? FLAG_CHROMA : 0);
108 }
109 
110 static av_always_inline int cmp_direct_inline(MPVEncContext *const s, const int x, const int y, const int subx, const int suby,
111  const int size, const int h, int ref_index, int src_index,
112  me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel){
113  MotionEstContext *const c = &s->me;
114  const int stride= c->stride;
115  const int hx = subx + x * (1 << (1 + qpel));
116  const int hy = suby + y * (1 << (1 + qpel));
117  const uint8_t * const * const ref = c->ref[ref_index];
118  const uint8_t * const * const src = c->src[src_index];
119  int d;
120  //FIXME check chroma 4mv, (no crashes ...)
121  av_assert2(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1));
122  if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){
123  const int time_pp = s->c.pp_time;
124  const int time_pb = s->c.pb_time;
125  const int mask= 2*qpel+1;
126  if (s->c.mv_type == MV_TYPE_8X8) {
127  int i;
128  for(i=0; i<4; i++){
129  int fx = c->direct_basis_mv[i][0] + hx;
130  int fy = c->direct_basis_mv[i][1] + hy;
131  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));
132  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));
133  int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
134  int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
135 
136  uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1);
137  if(qpel){
138  c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride);
139  c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride);
140  }else{
141  c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8);
142  c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8);
143  }
144  }
145  }else{
146  int fx = c->direct_basis_mv[0][0] + hx;
147  int fy = c->direct_basis_mv[0][1] + hy;
148  int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp);
149  int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp);
150  int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
151  int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
152 
153  if(qpel){
154  c->qpel_put[1][fxy](c->temp , ref[0] + (fx>>2) + (fy>>2)*stride , stride);
155  c->qpel_put[1][fxy](c->temp + 8 , ref[0] + (fx>>2) + (fy>>2)*stride + 8 , stride);
156  c->qpel_put[1][fxy](c->temp + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8*stride, stride);
157  c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride);
158  c->qpel_avg[1][bxy](c->temp , ref[8] + (bx>>2) + (by>>2)*stride , stride);
159  c->qpel_avg[1][bxy](c->temp + 8 , ref[8] + (bx>>2) + (by>>2)*stride + 8 , stride);
160  c->qpel_avg[1][bxy](c->temp + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8*stride, stride);
161  c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride);
162  }else{
163  av_assert2((fx>>1) + 16*s->c.mb_x >= -16);
164  av_assert2((fy>>1) + 16*s->c.mb_y >= -16);
165  av_assert2((fx>>1) + 16*s->c.mb_x <= s->c.width);
166  av_assert2((fy>>1) + 16*s->c.mb_y <= s->c.height);
167  av_assert2((bx>>1) + 16*s->c.mb_x >= -16);
168  av_assert2((by>>1) + 16*s->c.mb_y >= -16);
169  av_assert2((bx>>1) + 16*s->c.mb_x <= s->c.width);
170  av_assert2((by>>1) + 16*s->c.mb_y <= s->c.height);
171 
172  c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16);
173  c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16);
174  }
175  }
176  d = cmp_func(s, c->temp, src[0], stride, 16);
177  }else
178  d= 256*256*256*32;
179  return d;
180 }
181 
182 static av_always_inline int cmp_inline(MPVEncContext *const s, const int x, const int y, const int subx, const int suby,
183  const int size, const int h, int ref_index, int src_index,
184  me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel, int chroma){
185  MotionEstContext *const c = &s->me;
186  const int stride= c->stride;
187  const int uvstride= c->uvstride;
188  const int dxy= subx + (suby<<(1+qpel)); //FIXME log2_subpel?
189  const int hx= subx + x*(1<<(1+qpel));
190  const int hy= suby + y*(1<<(1+qpel));
191  const uint8_t * const * const ref = c->ref[ref_index];
192  const uint8_t * const * const src = c->src[src_index];
193  int d;
194  //FIXME check chroma 4mv, (no crashes ...)
195  int uvdxy; /* no, it might not be used uninitialized */
196  if(dxy){
197  if(qpel){
198  if (h << size == 16) {
199  c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride); //FIXME prototype (add h)
200  } else if (size == 0 && h == 8) {
201  c->qpel_put[1][dxy](c->temp , ref[0] + x + y*stride , stride);
202  c->qpel_put[1][dxy](c->temp + 8, ref[0] + x + y*stride + 8, stride);
203  } else
204  av_assert2(0);
205  if(chroma){
206  int cx= hx/2;
207  int cy= hy/2;
208  cx= (cx>>1)|(cx&1);
209  cy= (cy>>1)|(cy&1);
210  uvdxy= (cx&1) + 2*(cy&1);
211  // FIXME x/y wrong, but MPEG-4 qpel is sick anyway, we should drop as much of it as possible in favor for H.264
212  }
213  }else{
214  c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);
215  if(chroma)
216  uvdxy= dxy | (x&1) | (2*(y&1));
217  }
218  d = cmp_func(s, c->temp, src[0], stride, h);
219  }else{
220  d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h);
221  if(chroma)
222  uvdxy= (x&1) + 2*(y&1);
223  }
224  if(chroma){
225  uint8_t * const uvtemp= c->temp + 16*stride;
226  c->hpel_put[size+1][uvdxy](uvtemp , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
227  c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
228  d += chroma_cmp_func(s, uvtemp , src[1], uvstride, h>>1);
229  d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1);
230  }
231  return d;
232 }
233 
234 static int cmp_simple(MPVEncContext *const s, const int x, const int y,
235  int ref_index, int src_index,
236  me_cmp_func cmp_func, me_cmp_func chroma_cmp_func){
237  return cmp_inline(s,x,y,0,0,0,16,ref_index,src_index, cmp_func, chroma_cmp_func, 0, 0);
238 }
239 
240 static int cmp_fpel_internal(MPVEncContext *const s, const int x, const int y,
241  const int size, const int h, int ref_index, int src_index,
242  me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
243  if(flags&FLAG_DIRECT){
244  return cmp_direct_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL);
245  }else{
246  return cmp_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA);
247  }
248 }
249 
250 static int cmp_internal(MPVEncContext *const s, const int x, const int y, const int subx, const int suby,
251  const int size, const int h, int ref_index, int src_index,
252  me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
253  if(flags&FLAG_DIRECT){
254  return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL);
255  }else{
256  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);
257  }
258 }
259 
260 /** @brief compares a block (either a full macroblock or a partition thereof)
261  against a proposed motion-compensated prediction of that block
262  */
263 static av_always_inline int cmp(MPVEncContext *const s, const int x, const int y, const int subx, const int suby,
264  const int size, const int h, int ref_index, int src_index,
265  me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
268  && flags==0 && h==16 && size==0 && subx==0 && suby==0){
269  return cmp_simple(s,x,y,ref_index,src_index, cmp_func, chroma_cmp_func);
270  }else if(av_builtin_constant_p(subx) && av_builtin_constant_p(suby)
271  && subx==0 && suby==0){
272  return cmp_fpel_internal(s,x,y,size,h,ref_index,src_index, cmp_func, chroma_cmp_func,flags);
273  }else{
274  return cmp_internal(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags);
275  }
276 }
277 
278 static int cmp_hpel(MPVEncContext *const s, const int x, const int y, const int subx, const int suby,
279  const int size, const int h, int ref_index, int src_index,
280  me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
281  if(flags&FLAG_DIRECT){
282  return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0);
283  }else{
284  return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA);
285  }
286 }
287 
288 static int cmp_qpel(MPVEncContext *const s, const int x, const int y, const int subx, const int suby,
289  const int size, const int h, int ref_index, int src_index,
290  me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
291  if(flags&FLAG_DIRECT){
292  return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1);
293  }else{
294  return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1, flags&FLAG_CHROMA);
295  }
296 }
297 
298 #include "motion_est_template.c"
299 
300 static int zero_cmp(MPVEncContext *const s, const uint8_t *a, const uint8_t *b,
301  ptrdiff_t stride, int h)
302 {
303  return 0;
304 }
305 
306 static void zero_hpel(uint8_t *a, const uint8_t *b, ptrdiff_t stride, int h){
307 }
308 
310  const MECmpContext *mecc, int mpvenc)
311 {
312  int cache_size = FFMIN(ME_MAP_SIZE>>ME_MAP_SHIFT, 1<<ME_MAP_SHIFT);
313  int dia_size = FFMAX(FFABS(avctx->dia_size) & 255, FFABS(avctx->pre_dia_size) & 255);
314  int ret;
315 
316  if (FFMIN(avctx->dia_size, avctx->pre_dia_size) < -FFMIN(ME_MAP_SIZE, MAX_SAB_SIZE)) {
317  av_log(avctx, AV_LOG_ERROR, "ME_MAP size is too small for SAB diamond\n");
318  return AVERROR(EINVAL);
319  }
320 
321  c->avctx = avctx;
322 
323  if (avctx->codec_id == AV_CODEC_ID_H261)
324  avctx->me_sub_cmp = avctx->me_cmp;
325 
326  if (cache_size < 2 * dia_size)
327  av_log(avctx, AV_LOG_INFO, "ME_MAP size may be a little small for the selected diamond size\n");
328 
329  ret = ff_set_cmp(mecc, c->me_pre_cmp, avctx->me_pre_cmp, mpvenc);
330  ret |= ff_set_cmp(mecc, c->me_cmp, avctx->me_cmp, mpvenc);
331  ret |= ff_set_cmp(mecc, c->me_sub_cmp, avctx->me_sub_cmp, mpvenc);
332  ret |= ff_set_cmp(mecc, c->mb_cmp, avctx->mb_cmp, mpvenc);
333  if (ret < 0)
334  return ret;
335 
336  c->sse = mecc->sse[0];
337  memcpy(c->pix_abs, mecc->pix_abs, sizeof(c->pix_abs));
338 
339  c->flags = get_flags(c, 0, avctx->me_cmp & FF_CMP_CHROMA);
340  c->sub_flags = get_flags(c, 0, avctx->me_sub_cmp & FF_CMP_CHROMA);
341  c->mb_flags = get_flags(c, 0, avctx->mb_cmp & FF_CMP_CHROMA);
342 
343  if (avctx->codec_id == AV_CODEC_ID_H261) {
344  c->sub_motion_search = no_sub_motion_search;
345  } else if (avctx->flags & AV_CODEC_FLAG_QPEL) {
346  c->sub_motion_search= qpel_motion_search;
347  }else{
348  if(c->avctx->me_sub_cmp&FF_CMP_CHROMA)
349  c->sub_motion_search= hpel_motion_search;
350  else if( c->avctx->me_sub_cmp == FF_CMP_SAD
351  && c->avctx-> me_cmp == FF_CMP_SAD
352  && c->avctx-> mb_cmp == FF_CMP_SAD)
353  c->sub_motion_search= sad_hpel_motion_search; // 2050 vs. 2450 cycles
354  else
355  c->sub_motion_search= hpel_motion_search;
356  }
357 
358  /* 8x8 fullpel search would need a 4x4 chroma compare, which we do
359  * not have yet, and even if we had, the motion estimation code
360  * does not expect it. */
361  if (avctx->codec_id != AV_CODEC_ID_SNOW) {
362  if ((avctx->me_cmp & FF_CMP_CHROMA) /* && !c->me_cmp[2] */)
363  c->me_cmp[2] = zero_cmp;
364  if ((avctx->me_sub_cmp & FF_CMP_CHROMA) && !c->me_sub_cmp[2])
365  c->me_sub_cmp[2] = zero_cmp;
366  }
367 
368  return 0;
369 }
370 
372 {
373  MotionEstContext *const c = &s->me;
374 
375 /*FIXME s->c.no_rounding b_type*/
376  if (c->avctx->flags & AV_CODEC_FLAG_QPEL) {
377  c->qpel_avg = s->c.qdsp.avg_qpel_pixels_tab;
378  if (s->c.no_rounding)
379  c->qpel_put = s->c.qdsp.put_no_rnd_qpel_pixels_tab;
380  else
381  c->qpel_put = s->c.qdsp.put_qpel_pixels_tab;
382  }
383  c->hpel_avg = s->c.hdsp.avg_pixels_tab;
384  if (s->c.no_rounding)
385  c->hpel_put = s->c.hdsp.put_no_rnd_pixels_tab;
386  else
387  c->hpel_put = s->c.hdsp.put_pixels_tab;
388 
389  if (s->c.linesize) {
390  c->stride = s->c.linesize;
391  c->uvstride = s->c.uvlinesize;
392  }else{
393  c->stride = 16*s->c.mb_width + 32;
394  c->uvstride = 8*s->c.mb_width + 16;
395  }
396  if (s->c.codec_id != AV_CODEC_ID_SNOW) {
397  c->hpel_put[2][0]= c->hpel_put[2][1]=
398  c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel;
399  }
400  /* Reset the average MB variance and scene change stats */
401  c->scene_change_score = 0;
402  c->mb_var_sum_temp =
403  c->mc_mb_var_sum_temp = 0;
404 }
405 
406 #define CHECK_SAD_HALF_MV(suffix, x, y) \
407 {\
408  d = c->pix_abs[size][(x ? 1 : 0) + (y ? 2 : 0)](NULL, pix, ptr + ((x) >> 1), stride, h); \
409  d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\
410  COPY3_IF_LT(dminh, d, dx, x, dy, y)\
411 }
412 
414  int *mx_ptr, int *my_ptr, int dmin,
415  int src_index, int ref_index,
416  int size, int h)
417 {
418  MotionEstContext *const c = &s->me;
419  const int penalty_factor= c->sub_penalty_factor;
420  int mx, my, dminh;
421  const uint8_t *pix, *ptr;
422  int stride= c->stride;
424 
425  av_assert2(c->sub_flags == 0);
426 
427  if(c->skip){
428  *mx_ptr = 0;
429  *my_ptr = 0;
430  return dmin;
431  }
432 
433  pix = c->src[src_index][0];
434 
435  mx = *mx_ptr;
436  my = *my_ptr;
437  ptr = c->ref[ref_index][0] + (my * stride) + mx;
438 
439  dminh = dmin;
440 
441  if (mx > xmin && mx < xmax &&
442  my > ymin && my < ymax) {
443  int dx=0, dy=0;
444  int d, pen_x, pen_y;
445  const int index= my*(1<<ME_MAP_SHIFT) + mx;
446  const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
447  const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
448  const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
449  const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
450  mx += mx;
451  my += my;
452 
453 
454  pen_x= pred_x + mx;
455  pen_y= pred_y + my;
456 
457  ptr-= stride;
458  if(t<=b){
459  CHECK_SAD_HALF_MV(y2 , 0, -1)
460  if(l<=r){
461  CHECK_SAD_HALF_MV(xy2, -1, -1)
462  if(t+r<=b+l){
463  CHECK_SAD_HALF_MV(xy2, +1, -1)
464  ptr+= stride;
465  }else{
466  ptr+= stride;
467  CHECK_SAD_HALF_MV(xy2, -1, +1)
468  }
469  CHECK_SAD_HALF_MV(x2 , -1, 0)
470  }else{
471  CHECK_SAD_HALF_MV(xy2, +1, -1)
472  if(t+l<=b+r){
473  CHECK_SAD_HALF_MV(xy2, -1, -1)
474  ptr+= stride;
475  }else{
476  ptr+= stride;
477  CHECK_SAD_HALF_MV(xy2, +1, +1)
478  }
479  CHECK_SAD_HALF_MV(x2 , +1, 0)
480  }
481  }else{
482  if(l<=r){
483  if(t+l<=b+r){
484  CHECK_SAD_HALF_MV(xy2, -1, -1)
485  ptr+= stride;
486  }else{
487  ptr+= stride;
488  CHECK_SAD_HALF_MV(xy2, +1, +1)
489  }
490  CHECK_SAD_HALF_MV(x2 , -1, 0)
491  CHECK_SAD_HALF_MV(xy2, -1, +1)
492  }else{
493  if(t+r<=b+l){
494  CHECK_SAD_HALF_MV(xy2, +1, -1)
495  ptr+= stride;
496  }else{
497  ptr+= stride;
498  CHECK_SAD_HALF_MV(xy2, -1, +1)
499  }
500  CHECK_SAD_HALF_MV(x2 , +1, 0)
501  CHECK_SAD_HALF_MV(xy2, +1, +1)
502  }
503  CHECK_SAD_HALF_MV(y2 , 0, +1)
504  }
505  mx+=dx;
506  my+=dy;
507 
508  }else{
509  mx += mx;
510  my += my;
511  }
512 
513  *mx_ptr = mx;
514  *my_ptr = my;
515  return dminh;
516 }
517 
518 static inline void set_p_mv_tables(MPVEncContext *const s, int mx, int my, int mv4)
519 {
520  const int xy = s->c.mb_x + s->c.mb_y * s->c.mb_stride;
521 
522  s->p_mv_table[xy][0] = mx;
523  s->p_mv_table[xy][1] = my;
524 
525  /* has already been set to the 4 MV if 4MV is done */
526  if(mv4){
527  int mot_xy = s->c.block_index[0];
528 
529  s->c.cur_pic.motion_val[0][mot_xy ][0] = mx;
530  s->c.cur_pic.motion_val[0][mot_xy ][1] = my;
531  s->c.cur_pic.motion_val[0][mot_xy + 1][0] = mx;
532  s->c.cur_pic.motion_val[0][mot_xy + 1][1] = my;
533 
534  mot_xy += s->c.b8_stride;
535  s->c.cur_pic.motion_val[0][mot_xy ][0] = mx;
536  s->c.cur_pic.motion_val[0][mot_xy ][1] = my;
537  s->c.cur_pic.motion_val[0][mot_xy + 1][0] = mx;
538  s->c.cur_pic.motion_val[0][mot_xy + 1][1] = my;
539  }
540 }
541 
542 /**
543  * get fullpel ME search limits.
544  */
545 static inline void get_limits(MPVEncContext *const s, int x, int y, int bframe)
546 {
547  MotionEstContext *const c = &s->me;
548  int range= c->avctx->me_range >> (1 + !!(c->flags&FLAG_QPEL));
549  int max_range = MAX_MV >> (1 + !!(c->flags&FLAG_QPEL));
550 /*
551  if(c->avctx->me_range) c->range= c->avctx->me_range >> 1;
552  else c->range= 16;
553 */
554  if (s->c.unrestricted_mv) {
555  c->xmin = - x - 16;
556  c->ymin = - y - 16;
557  c->xmax = - x + s->c.width;
558  c->ymax = - y + s->c.height;
559  } else if (!(av_builtin_constant_p(bframe) && bframe) && s->c.out_format == FMT_H261){
560  // Search range of H.261 is different from other codec standards
561  c->xmin = (x > 15) ? - 15 : 0;
562  c->ymin = (y > 15) ? - 15 : 0;
563  c->xmax = (x < s->c.mb_width * 16 - 16) ? 15 : 0;
564  c->ymax = (y < s->c.mb_height * 16 - 16) ? 15 : 0;
565  } else {
566  c->xmin = - x;
567  c->ymin = - y;
568  c->xmax = - x + s->c.mb_width *16 - 16;
569  c->ymax = - y + s->c.mb_height*16 - 16;
570  }
571  if(!range || range > max_range)
572  range = max_range;
573  if(range){
574  c->xmin = FFMAX(c->xmin,-range);
575  c->xmax = FFMIN(c->xmax, range);
576  c->ymin = FFMAX(c->ymin,-range);
577  c->ymax = FFMIN(c->ymax, range);
578  }
579 }
580 
581 static inline void init_mv4_ref(MotionEstContext *c){
582  const int stride= c->stride;
583 
584  c->ref[1][0] = c->ref[0][0] + 8;
585  c->ref[2][0] = c->ref[0][0] + 8*stride;
586  c->ref[3][0] = c->ref[2][0] + 8;
587  c->src[1][0] = c->src[0][0] + 8;
588  c->src[2][0] = c->src[0][0] + 8*stride;
589  c->src[3][0] = c->src[2][0] + 8;
590 }
591 
592 static inline int h263_mv4_search(MPVEncContext *const s, int mx, int my, int shift)
593 {
594  MotionEstContext *const c = &s->me;
595  const int size= 1;
596  const int h=8;
597  int block;
598  int P[10][2];
599  int dmin_sum=0, mx4_sum=0, my4_sum=0, i;
600  int same=1;
601  const int stride= c->stride;
602  const uint8_t *mv_penalty = c->current_mv_penalty;
603  int safety_clipping = s->c.unrestricted_mv && (s->c.width&15) && (s->c.height&15);
604 
605  init_mv4_ref(c);
606 
607  for(block=0; block<4; block++){
608  int mx4, my4;
609  int pred_x4, pred_y4;
610  int dmin4;
611  static const int off[4]= {2, 1, 1, -1};
612  const int mot_stride = s->c.b8_stride;
613  const int mot_xy = s->c.block_index[block];
614 
615  if(safety_clipping){
616  c->xmax = - 16*s->c.mb_x + s->c.width - 8*(block &1);
617  c->ymax = - 16*s->c.mb_y + s->c.height - 8*(block>>1);
618  }
619 
620  P_LEFT[0] = s->c.cur_pic.motion_val[0][mot_xy - 1][0];
621  P_LEFT[1] = s->c.cur_pic.motion_val[0][mot_xy - 1][1];
622 
623  if (P_LEFT[0] > c->xmax * (1 << shift)) P_LEFT[0] = c->xmax * (1 << shift);
624 
625  /* special case for first line */
626  if (s->c.first_slice_line && block < 2) {
627  c->pred_x= pred_x4= P_LEFT[0];
628  c->pred_y= pred_y4= P_LEFT[1];
629  } else {
630  P_TOP[0] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride ][0];
631  P_TOP[1] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride ][1];
632  P_TOPRIGHT[0] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride + off[block]][0];
633  P_TOPRIGHT[1] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride + off[block]][1];
634  if (P_TOP[1] > c->ymax * (1 << shift)) P_TOP[1] = c->ymax * (1 << shift);
635  if (P_TOPRIGHT[0] < c->xmin * (1 << shift)) P_TOPRIGHT[0] = c->xmin * (1 << shift);
636  if (P_TOPRIGHT[0] > c->xmax * (1 << shift)) P_TOPRIGHT[0] = c->xmax * (1 << shift);
637  if (P_TOPRIGHT[1] > c->ymax * (1 << shift)) P_TOPRIGHT[1] = c->ymax * (1 << shift);
638 
639  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
640  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
641 
642  c->pred_x= pred_x4 = P_MEDIAN[0];
643  c->pred_y= pred_y4 = P_MEDIAN[1];
644  }
645  P_MV1[0]= mx;
646  P_MV1[1]= my;
647  if(safety_clipping)
648  for(i=1; i<10; i++){
649  if (s->c.first_slice_line && block < 2 && i > 1 && i < 9)
650  continue;
651  if (i>4 && i<9)
652  continue;
653  if (P[i][0] > c->xmax * (1 << shift)) P[i][0] = c->xmax * (1 << shift);
654  if (P[i][1] > c->ymax * (1 << shift)) P[i][1] = c->ymax * (1 <<shift );
655  }
656 
657  dmin4 = epzs_motion_search2(s, &mx4, &my4, P, block, block, s->p_mv_table, (1<<16)>>shift, 1);
658 
659  dmin4= c->sub_motion_search(s, &mx4, &my4, dmin4, block, block, size, h);
660 
661  if (c->me_sub_cmp[0] != c->mb_cmp[0]) {
662  int dxy;
663  const int offset= ((block&1) + (block>>1)*stride)*8;
664  uint8_t *dest_y = c->scratchpad + offset;
665  if (s->c.quarter_sample) {
666  const uint8_t *ref = c->ref[block][0] + (mx4>>2) + (my4>>2)*stride;
667  dxy = ((my4 & 3) << 2) | (mx4 & 3);
668 
669  c->qpel_put[1][dxy](dest_y, ref, stride);
670  }else{
671  const uint8_t *ref = c->ref[block][0] + (mx4>>1) + (my4>>1)*stride;
672  dxy = ((my4 & 1) << 1) | (mx4 & 1);
673 
674  c->hpel_put[1][dxy](dest_y, ref, stride, h);
675  }
676  dmin_sum+= (mv_penalty[mx4-pred_x4] + mv_penalty[my4-pred_y4])*c->mb_penalty_factor;
677  }else
678  dmin_sum+= dmin4;
679 
680  if (s->c.quarter_sample) {
681  mx4_sum+= mx4/2;
682  my4_sum+= my4/2;
683  }else{
684  mx4_sum+= mx4;
685  my4_sum+= my4;
686  }
687 
688  s->c.cur_pic.motion_val[0][s->c.block_index[block]][0] = mx4;
689  s->c.cur_pic.motion_val[0][s->c.block_index[block]][1] = my4;
690 
691  if(mx4 != mx || my4 != my) same=0;
692  }
693 
694  if(same)
695  return INT_MAX;
696 
697  if (c->me_sub_cmp[0] != c->mb_cmp[0]) {
698  dmin_sum += c->mb_cmp[0](s,
699  s->new_pic->data[0] +
700  s->c.mb_x * 16 + s->c.mb_y * 16 * stride,
701  c->scratchpad, stride, 16);
702  }
703 
704  if(c->avctx->mb_cmp&FF_CMP_CHROMA){
705  int dxy;
706  int mx, my;
707  int offset;
708 
709  mx= ff_h263_round_chroma(mx4_sum);
710  my= ff_h263_round_chroma(my4_sum);
711  dxy = ((my & 1) << 1) | (mx & 1);
712 
713  offset = (s->c.mb_x*8 + (mx>>1)) + (s->c.mb_y*8 + (my>>1))*s->c.uvlinesize;
714 
715  c->hpel_put[1][dxy](c->scratchpad , s->c.last_pic.data[1] + offset, s->c.uvlinesize, 8);
716  c->hpel_put[1][dxy](c->scratchpad + 8, s->c.last_pic.data[2] + offset, s->c.uvlinesize, 8);
717 
718  dmin_sum += c->mb_cmp[1](s, s->new_pic->data[1] + s->c.mb_x * 8 + s->c.mb_y * 8 * s->c.uvlinesize, c->scratchpad, s->c.uvlinesize, 8);
719  dmin_sum += c->mb_cmp[1](s, s->new_pic->data[2] + s->c.mb_x * 8 + s->c.mb_y * 8 * s->c.uvlinesize, c->scratchpad + 8, s->c.uvlinesize, 8);
720  }
721 
722  c->pred_x= mx;
723  c->pred_y= my;
724 
725  switch(c->avctx->mb_cmp&0xFF){
726  /*case FF_CMP_SSE:
727  return dmin_sum+ 32*s->c.qscale*s->c.qscale;*/
728  case FF_CMP_RD:
729  return dmin_sum;
730  default:
731  return dmin_sum+ 11*c->mb_penalty_factor;
732  }
733 }
734 
735 static inline void init_interlaced_ref(MPVEncContext *const s, int ref_index)
736 {
737  MotionEstContext *const c = &s->me;
738 
739  c->ref[1+ref_index][0] = c->ref[0+ref_index][0] + s->c.linesize;
740  c->src[1][0] = c->src[0][0] + s->c.linesize;
741  if(c->flags & FLAG_CHROMA){
742  c->ref[1+ref_index][1] = c->ref[0+ref_index][1] + s->c.uvlinesize;
743  c->ref[1+ref_index][2] = c->ref[0+ref_index][2] + s->c.uvlinesize;
744  c->src[1][1] = c->src[0][1] + s->c.uvlinesize;
745  c->src[1][2] = c->src[0][2] + s->c.uvlinesize;
746  }
747 }
748 
749 static int interlaced_search(MPVEncContext *const s, int ref_index,
750  int16_t (*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int mx, int my, int user_field_select)
751 {
752  MotionEstContext *const c = &s->me;
753  const int size=0;
754  const int h=8;
755  int block;
756  int P[10][2];
757  const uint8_t * const mv_penalty = c->current_mv_penalty;
758  int same=1;
759  const int stride = 2*s->c.linesize;
760  int dmin_sum= 0;
761  const int mot_stride = s->c.mb_stride;
762  const int xy = s->c.mb_x + s->c.mb_y*mot_stride;
763 
764  c->ymin>>=1;
765  c->ymax>>=1;
766  c->stride<<=1;
767  c->uvstride<<=1;
768  init_interlaced_ref(s, ref_index);
769 
770  for(block=0; block<2; block++){
771  int field_select;
772  int best_dmin= INT_MAX;
773  int best_field= -1;
774 
775  for(field_select=0; field_select<2; field_select++){
776  int dmin, mx_i, my_i;
777  int16_t (*mv_table)[2]= mv_tables[block][field_select];
778 
779  if(user_field_select){
780  av_assert1(field_select==0 || field_select==1);
781  av_assert1(field_select_tables[block][xy]==0 || field_select_tables[block][xy]==1);
782  if(field_select_tables[block][xy] != field_select)
783  continue;
784  }
785 
786  P_LEFT[0] = mv_table[xy - 1][0];
787  P_LEFT[1] = mv_table[xy - 1][1];
788  if(P_LEFT[0] > (c->xmax<<1)) P_LEFT[0] = (c->xmax<<1);
789 
790  c->pred_x= P_LEFT[0];
791  c->pred_y= P_LEFT[1];
792 
793  if (!s->c.first_slice_line) {
794  P_TOP[0] = mv_table[xy - mot_stride][0];
795  P_TOP[1] = mv_table[xy - mot_stride][1];
796  P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0];
797  P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1];
798  if(P_TOP[1] > (c->ymax<<1)) P_TOP[1] = (c->ymax<<1);
799  if (P_TOPRIGHT[0] < c->xmin * (1 << 1)) P_TOPRIGHT[0] = c->xmin * (1 << 1);
800  if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1);
801  if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1);
802 
803  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
804  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
805  }
806  P_MV1[0]= mx; //FIXME not correct if block != field_select
807  P_MV1[1]= my / 2;
808 
809  dmin = epzs_motion_search2(s, &mx_i, &my_i, P, block, field_select+ref_index, mv_table, (1<<16)>>1, 0);
810 
811  dmin= c->sub_motion_search(s, &mx_i, &my_i, dmin, block, field_select+ref_index, size, h);
812 
813  mv_table[xy][0]= mx_i;
814  mv_table[xy][1]= my_i;
815 
816  if (c->me_sub_cmp[0] != c->mb_cmp[0]) {
817  int dxy;
818 
819  //FIXME chroma ME
820  const uint8_t *ref = c->ref[field_select+ref_index][0] + (mx_i>>1) + (my_i>>1)*stride;
821  dxy = ((my_i & 1) << 1) | (mx_i & 1);
822 
823  c->hpel_put[size][dxy](c->scratchpad, ref, stride, h);
824  dmin = c->mb_cmp[size](s, c->src[block][0], c->scratchpad, stride, h);
825  dmin+= (mv_penalty[mx_i-c->pred_x] + mv_penalty[my_i-c->pred_y] + 1)*c->mb_penalty_factor;
826  }else
827  dmin+= c->mb_penalty_factor; //field_select bits
828 
829  dmin += field_select != block; //slightly prefer same field
830 
831  if(dmin < best_dmin){
832  best_dmin= dmin;
833  best_field= field_select;
834  }
835  }
836  {
837  int16_t (*mv_table)[2]= mv_tables[block][best_field];
838 
839  if(mv_table[xy][0] != mx) same=0; //FIXME check if these checks work and are any good at all
840  if(mv_table[xy][1]&1) same=0;
841  if(mv_table[xy][1]*2 != my) same=0;
842  if(best_field != block) same=0;
843  }
844 
845  field_select_tables[block][xy]= best_field;
846  dmin_sum += best_dmin;
847  }
848 
849  c->ymin *= 2;
850  c->ymax<<=1;
851  c->stride>>=1;
852  c->uvstride>>=1;
853 
854  if(same)
855  return INT_MAX;
856 
857  switch(c->avctx->mb_cmp&0xFF){
858  /*case FF_CMP_SSE:
859  return dmin_sum+ 32*s->c.qscale*s->c.qscale;*/
860  case FF_CMP_RD:
861  return dmin_sum;
862  default:
863  return dmin_sum+ 11*c->mb_penalty_factor;
864  }
865 }
866 
867 static inline int get_penalty_factor(int lambda, int lambda2, int type){
868  switch(type&0xFF){
869  default:
870  case FF_CMP_SAD:
871  return lambda>>FF_LAMBDA_SHIFT;
872  case FF_CMP_DCT:
873  return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
874  case FF_CMP_W53:
875  return (4*lambda)>>(FF_LAMBDA_SHIFT);
876  case FF_CMP_W97:
877  return (2*lambda)>>(FF_LAMBDA_SHIFT);
878  case FF_CMP_SATD:
879  case FF_CMP_DCT264:
880  return (2*lambda)>>FF_LAMBDA_SHIFT;
881  case FF_CMP_RD:
882  case FF_CMP_PSNR:
883  case FF_CMP_SSE:
884  case FF_CMP_NSSE:
885  return lambda2>>FF_LAMBDA_SHIFT;
886  case FF_CMP_BIT:
887  case FF_CMP_MEDIAN_SAD:
888  return 1;
889  }
890 }
891 
893  int mb_x, int mb_y)
894 {
895  MotionEstContext *const c = &s->me;
896  const uint8_t *pix, *ppix;
897  int sum, mx = 0, my = 0, dmin = 0;
898  int varc; ///< the variance of the block (sum of squared (p[y][x]-average))
899  int vard; ///< sum of squared differences with the estimated motion vector
900  int P[10][2];
901  const int shift = 1 + s->c.quarter_sample;
902  int mb_type=0;
903 
904  init_ref(c, s->new_pic->data, s->c.last_pic.data, NULL, 16*mb_x, 16*mb_y, 0);
905 
906  av_assert0(s->c.quarter_sample == 0 || s->c.quarter_sample == 1);
907  av_assert0(s->c.linesize == c->stride);
908  av_assert0(s->c.uvlinesize == c->uvstride);
909 
910  c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
911  c->sub_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
912  c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
913  c->current_mv_penalty = c->mv_penalty[s->c.f_code] + MAX_DMV;
914 
915  get_limits(s, 16*mb_x, 16*mb_y, 0);
916  c->skip=0;
917 
918  /* intra / predictive decision */
919  pix = c->src[0][0];
920  sum = s->mpvencdsp.pix_sum(pix, s->c.linesize);
921  varc = s->mpvencdsp.pix_norm1(pix, s->c.linesize) -
922  (((unsigned) sum * sum) >> 8) + 500;
923 
924  s->mb_mean[s->c.mb_stride * mb_y + mb_x] = (sum + 128) >> 8;
925  s->mb_var [s->c.mb_stride * mb_y + mb_x] = (varc + 128) >> 8;
926  c->mb_var_sum_temp += (varc+128)>>8;
927 
928  if (c->motion_est != FF_ME_ZERO) {
929  const int mot_stride = s->c.b8_stride;
930  const int mot_xy = s->c.block_index[0];
931 
932  P_LEFT[0] = s->c.cur_pic.motion_val[0][mot_xy - 1][0];
933  P_LEFT[1] = s->c.cur_pic.motion_val[0][mot_xy - 1][1];
934 
935  if (P_LEFT[0] > (c->xmax << shift))
936  P_LEFT[0] = c->xmax << shift;
937 
938  if (!s->c.first_slice_line) {
939  P_TOP[0] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride ][0];
940  P_TOP[1] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride ][1];
941  P_TOPRIGHT[0] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride + 2][0];
942  P_TOPRIGHT[1] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride + 2][1];
943  if (P_TOP[1] > (c->ymax << shift))
944  P_TOP[1] = c->ymax << shift;
945  if (P_TOPRIGHT[0] < (c->xmin * (1 << shift)))
946  P_TOPRIGHT[0] = c->xmin * (1 << shift);
947  if (P_TOPRIGHT[1] > (c->ymax * (1 << shift)))
948  P_TOPRIGHT[1] = c->ymax * (1 << shift);
949 
950  P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
951  P_MEDIAN[1] = mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
952 
953  if (s->c.out_format == FMT_H263) {
954  c->pred_x = P_MEDIAN[0];
955  c->pred_y = P_MEDIAN[1];
956  } else { /* MPEG-1 at least */
957  c->pred_x = P_LEFT[0];
958  c->pred_y = P_LEFT[1];
959  }
960  } else {
961  c->pred_x = P_LEFT[0];
962  c->pred_y = P_LEFT[1];
963  }
964  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
965  }
966 
967  /* At this point (mx,my) are full-pell and the relative displacement */
968  ppix = c->ref[0][0] + (my * s->c.linesize) + mx;
969 
970  vard = c->sse(NULL, pix, ppix, s->c.linesize, 16);
971 
972  s->mc_mb_var[s->c.mb_stride * mb_y + mb_x] = (vard+128)>>8;
973  c->mc_mb_var_sum_temp += (vard+128)>>8;
974 
975  if (c->avctx->mb_decision > FF_MB_DECISION_SIMPLE) {
976  int p_score = FFMIN(vard, varc - 500 + (s->lambda2 >> FF_LAMBDA_SHIFT)*100);
977  int i_score = varc - 500 + (s->lambda2 >> FF_LAMBDA_SHIFT)*20;
978  c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
979 
980  if (vard*2 + 200*256 > varc && !s->intra_penalty)
981  mb_type|= CANDIDATE_MB_TYPE_INTRA;
982  if (varc*2 + 200*256 > vard || s->c.qscale > 24){
983 // if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){
984  mb_type|= CANDIDATE_MB_TYPE_INTER;
985  c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
986  if (s->mpv_flags & FF_MPV_FLAG_MV0)
987  if(mx || my)
988  mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference
989  }else{
990  mx *= 1 << shift;
991  my *= 1 << shift;
992  }
993  if ((c->avctx->flags & AV_CODEC_FLAG_4MV)
994  && !c->skip && varc>50<<8 && vard>10<<8){
995  if(h263_mv4_search(s, mx, my, shift) < INT_MAX)
996  mb_type|=CANDIDATE_MB_TYPE_INTER4V;
997 
998  set_p_mv_tables(s, mx, my, 0);
999  }else
1000  set_p_mv_tables(s, mx, my, 1);
1001  if ((c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)
1002  && !c->skip){ //FIXME varc/d checks
1003  if(interlaced_search(s, 0, s->c.p_field_mv_table, s->p_field_select_table, mx, my, 0) < INT_MAX)
1004  mb_type |= CANDIDATE_MB_TYPE_INTER_I;
1005  }
1006  }else{
1007  int intra_score, i;
1008  mb_type= CANDIDATE_MB_TYPE_INTER;
1009 
1010  dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1011  if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1012  dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
1013 
1014  if ((c->avctx->flags & AV_CODEC_FLAG_4MV)
1015  && !c->skip && varc>50<<8 && vard>10<<8){
1016  int dmin4= h263_mv4_search(s, mx, my, shift);
1017  if(dmin4 < dmin){
1018  mb_type= CANDIDATE_MB_TYPE_INTER4V;
1019  dmin=dmin4;
1020  }
1021  }
1022  if ((c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)
1023  && !c->skip){ //FIXME varc/d checks
1024  int dmin_i= interlaced_search(s, 0, s->c.p_field_mv_table, s->p_field_select_table, mx, my, 0);
1025  if(dmin_i < dmin){
1026  mb_type = CANDIDATE_MB_TYPE_INTER_I;
1027  dmin= dmin_i;
1028  }
1029  }
1030 
1032 
1033  /* get intra luma score */
1034  if((c->avctx->mb_cmp&0xFF)==FF_CMP_SSE){
1035  intra_score= varc - 500;
1036  }else{
1037  unsigned mean = (sum+128)>>8;
1038  mean*= 0x01010101;
1039 
1040  for(i=0; i<16; i++){
1041  *(uint32_t*)(&c->scratchpad[i*s->c.linesize+ 0]) = mean;
1042  *(uint32_t*)(&c->scratchpad[i*s->c.linesize+ 4]) = mean;
1043  *(uint32_t*)(&c->scratchpad[i*s->c.linesize+ 8]) = mean;
1044  *(uint32_t*)(&c->scratchpad[i*s->c.linesize+12]) = mean;
1045  }
1046 
1047  intra_score= c->mb_cmp[0](s, c->scratchpad, pix, s->c.linesize, 16);
1048  }
1049  intra_score += c->mb_penalty_factor*16 + s->intra_penalty;
1050 
1051  if(intra_score < dmin){
1052  mb_type= CANDIDATE_MB_TYPE_INTRA;
1053  s->c.cur_pic.mb_type[mb_y*s->c.mb_stride + mb_x] = CANDIDATE_MB_TYPE_INTRA; //FIXME cleanup
1054  }else
1055  s->c.cur_pic.mb_type[mb_y*s->c.mb_stride + mb_x] = 0;
1056 
1057  {
1058  int p_score = FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
1059  int i_score = varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
1060  c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
1061  }
1062  }
1063 
1064  s->mb_type[mb_y*s->c.mb_stride + mb_x] = mb_type;
1065 }
1066 
1068  int mb_x, int mb_y)
1069 {
1070  MotionEstContext *const c = &s->me;
1071  int mx, my, dmin;
1072  int P[10][2];
1073  const int shift = 1 + s->c.quarter_sample;
1074  const int xy = mb_x + mb_y*s->c.mb_stride;
1075  init_ref(c, s->new_pic->data, s->c.last_pic.data, NULL, 16*mb_x, 16*mb_y, 0);
1076 
1077  av_assert0(s->c.quarter_sample == 0 || s->c.quarter_sample == 1);
1078 
1079  c->pre_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_pre_cmp);
1080  c->current_mv_penalty = c->mv_penalty[s->c.f_code] + MAX_DMV;
1081 
1082  get_limits(s, 16*mb_x, 16*mb_y, 0);
1083  c->skip=0;
1084 
1085  P_LEFT[0] = s->p_mv_table[xy + 1][0];
1086  P_LEFT[1] = s->p_mv_table[xy + 1][1];
1087 
1088  if(P_LEFT[0] < (c->xmin<<shift)) P_LEFT[0] = (c->xmin<<shift);
1089 
1090  /* special case for first line */
1091  if (s->c.first_slice_line) {
1092  c->pred_x= P_LEFT[0];
1093  c->pred_y= P_LEFT[1];
1094  P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]=
1095  P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0; //FIXME
1096  } else {
1097  P_TOP[0] = s->p_mv_table[xy + s->c.mb_stride ][0];
1098  P_TOP[1] = s->p_mv_table[xy + s->c.mb_stride ][1];
1099  P_TOPRIGHT[0] = s->p_mv_table[xy + s->c.mb_stride - 1][0];
1100  P_TOPRIGHT[1] = s->p_mv_table[xy + s->c.mb_stride - 1][1];
1101  if(P_TOP[1] < (c->ymin<<shift)) P_TOP[1] = (c->ymin<<shift);
1102  if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
1103  if(P_TOPRIGHT[1] < (c->ymin<<shift)) P_TOPRIGHT[1]= (c->ymin<<shift);
1104 
1105  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1106  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1107 
1108  c->pred_x = P_MEDIAN[0];
1109  c->pred_y = P_MEDIAN[1];
1110  }
1111 
1112  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
1113 
1114  s->p_mv_table[xy][0] = mx<<shift;
1115  s->p_mv_table[xy][1] = my<<shift;
1116 
1117  return dmin;
1118 }
1119 
1120 static int estimate_motion_b(MPVEncContext *const s, int mb_x, int mb_y,
1121  int16_t (*mv_table)[2], int ref_index, int f_code)
1122 {
1123  MotionEstContext *const c = &s->me;
1124  int mx = 0, my = 0, dmin = 0;
1125  int P[10][2];
1126  const int shift= 1+s->c.quarter_sample;
1127  const int mot_stride = s->c.mb_stride;
1128  const int mot_xy = mb_y*mot_stride + mb_x;
1129  const uint8_t * const mv_penalty = c->mv_penalty[f_code] + MAX_DMV;
1130  int mv_scale;
1131 
1132  c->current_mv_penalty= mv_penalty;
1133 
1134  get_limits(s, 16*mb_x, 16*mb_y, 1);
1135 
1136  if (c->motion_est != FF_ME_ZERO) {
1137  P_LEFT[0] = mv_table[mot_xy - 1][0];
1138  P_LEFT[1] = mv_table[mot_xy - 1][1];
1139 
1140  if (P_LEFT[0] > (c->xmax << shift)) P_LEFT[0] = (c->xmax << shift);
1141 
1142  /* special case for first line */
1143  if (!s->c.first_slice_line) {
1144  P_TOP[0] = mv_table[mot_xy - mot_stride ][0];
1145  P_TOP[1] = mv_table[mot_xy - mot_stride ][1];
1146  P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1][0];
1147  P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1][1];
1148  if (P_TOP[1] > (c->ymax << shift)) P_TOP[1] = (c->ymax << shift);
1149  if (P_TOPRIGHT[0] < c->xmin * (1 << shift)) P_TOPRIGHT[0] = c->xmin * (1 << shift);
1150  if (P_TOPRIGHT[1] > (c->ymax << shift)) P_TOPRIGHT[1] = (c->ymax << shift);
1151 
1152  P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1153  P_MEDIAN[1] = mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1154  }
1155  c->pred_x = P_LEFT[0];
1156  c->pred_y = P_LEFT[1];
1157 
1158  if(mv_table == s->b_forw_mv_table){
1159  mv_scale= (s->c.pb_time<<16) / (s->c.pp_time<<shift);
1160  }else{
1161  mv_scale = ((s->c.pb_time - s->c.pp_time) * (1 << 16)) / (s->c.pp_time<<shift);
1162  }
1163 
1164  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->p_mv_table, mv_scale, 0, 16);
1165  }
1166 
1167  dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, ref_index, 0, 16);
1168 
1169  if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1170  dmin= get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1);
1171 
1172 // s->mb_type[mb_y*s->c.mb_width + mb_x]= mb_type;
1173  mv_table[mot_xy][0]= mx;
1174  mv_table[mot_xy][1]= my;
1175 
1176  return dmin;
1177 }
1178 
1179 static inline int check_bidir_mv(MPVEncContext *const s,
1180  int motion_fx, int motion_fy,
1181  int motion_bx, int motion_by,
1182  int pred_fx, int pred_fy,
1183  int pred_bx, int pred_by,
1184  int size, int h)
1185 {
1186  //FIXME optimize?
1187  //FIXME better f_code prediction (max mv & distance)
1188  //FIXME pointers
1189  MotionEstContext *const c = &s->me;
1190  const uint8_t * const mv_penalty_f = c->mv_penalty[s->c.f_code] + MAX_DMV; // f_code of the prev frame
1191  const uint8_t * const mv_penalty_b = c->mv_penalty[s->c.b_code] + MAX_DMV; // f_code of the prev frame
1192  int stride= c->stride;
1193  uint8_t *dest_y = c->scratchpad;
1194  const uint8_t *ptr;
1195  int dxy;
1196  int src_x, src_y;
1197  int fbmin;
1198  const uint8_t *const *src_data = c->src[0];
1199  const uint8_t *const *ref_data = c->ref[0];
1200  const uint8_t *const *ref2_data = c->ref[2];
1201 
1202  if(s->c.quarter_sample){
1203  dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
1204  src_x = motion_fx >> 2;
1205  src_y = motion_fy >> 2;
1206 
1207  ptr = ref_data[0] + (src_y * stride) + src_x;
1208  s->c.qdsp.put_qpel_pixels_tab[0][dxy](dest_y, ptr, stride);
1209 
1210  dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
1211  src_x = motion_bx >> 2;
1212  src_y = motion_by >> 2;
1213 
1214  ptr = ref2_data[0] + (src_y * stride) + src_x;
1215  s->c.qdsp.avg_qpel_pixels_tab[size][dxy](dest_y, ptr, stride);
1216  }else{
1217  dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1218  src_x = motion_fx >> 1;
1219  src_y = motion_fy >> 1;
1220 
1221  ptr = ref_data[0] + (src_y * stride) + src_x;
1222  s->c.hdsp.put_pixels_tab[size][dxy](dest_y , ptr , stride, h);
1223 
1224  dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
1225  src_x = motion_bx >> 1;
1226  src_y = motion_by >> 1;
1227 
1228  ptr = ref2_data[0] + (src_y * stride) + src_x;
1229  s->c.hdsp.avg_pixels_tab[size][dxy](dest_y , ptr , stride, h);
1230  }
1231 
1232  fbmin = (mv_penalty_f[motion_fx-pred_fx] + mv_penalty_f[motion_fy-pred_fy])*c->mb_penalty_factor
1233  +(mv_penalty_b[motion_bx-pred_bx] + mv_penalty_b[motion_by-pred_by])*c->mb_penalty_factor
1234  + c->mb_cmp[size](s, src_data[0], dest_y, stride, h); // FIXME new_pic
1235 
1236  if(c->avctx->mb_cmp&FF_CMP_CHROMA){
1237  }
1238  //FIXME CHROMA !!!
1239 
1240  return fbmin;
1241 }
1242 
1243 /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1244 static inline int bidir_refine(MPVEncContext *const s, int mb_x, int mb_y)
1245 {
1246  MotionEstContext *const c = &s->me;
1247  const int mot_stride = s->c.mb_stride;
1248  const int xy = mb_y *mot_stride + mb_x;
1249  int fbmin;
1250  int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
1251  int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
1252  int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
1253  int pred_by= s->b_bidir_back_mv_table[xy-1][1];
1254  int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
1255  int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
1256  int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
1257  int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
1258  const int flags= c->sub_flags;
1259  const int qpel= flags&FLAG_QPEL;
1260  const int shift= 1+qpel;
1261  const int xmin= c->xmin * (1 << shift);
1262  const int ymin= c->ymin * (1 << shift);
1263  const int xmax= c->xmax<<shift;
1264  const int ymax= c->ymax<<shift;
1265 #define HASH(fx,fy,bx,by) ((fx)+17*(fy)+63*(bx)+117*(by))
1266 #define HASH8(fx,fy,bx,by) ((uint8_t)HASH(fx,fy,bx,by))
1267  int hashidx= HASH(motion_fx,motion_fy, motion_bx, motion_by);
1268  uint8_t map[256] = { 0 };
1269 
1270  map[hashidx&255] = 1;
1271 
1272  fbmin= check_bidir_mv(s, motion_fx, motion_fy,
1273  motion_bx, motion_by,
1274  pred_fx, pred_fy,
1275  pred_bx, pred_by,
1276  0, 16);
1277 
1278  if (c->avctx->bidir_refine) {
1279  int end;
1280  static const uint8_t limittab[5]={0,8,32,64,80};
1281  const int limit = limittab[c->avctx->bidir_refine];
1282  static const int8_t vect[][4]={
1283 { 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},
1284 
1285 { 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},
1286 { 0, 1, 0, 1}, { 0,-1, 0,-1}, { 1, 0, 1, 0}, {-1, 0,-1, 0},
1287 { 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},
1288 { 0,-1, 0, 1}, { 0, 1, 0,-1}, {-1, 0, 1, 0}, { 1, 0,-1, 0},
1289 
1290 { 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},
1291 { 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},
1292 { 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},
1293 { 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},
1294 
1295 { 1, 1, 1, 1}, {-1,-1,-1,-1},
1296 { 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},
1297 { 1, 1,-1,-1}, {-1,-1, 1, 1}, { 1,-1,-1, 1}, {-1, 1, 1,-1}, { 1,-1, 1,-1}, {-1, 1,-1, 1},
1298  };
1299  static const uint8_t hash[]={
1300 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),
1301 
1302 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),
1303 HASH8( 0, 1, 0, 1), HASH8( 0,-1, 0,-1), HASH8( 1, 0, 1, 0), HASH8(-1, 0,-1, 0),
1304 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),
1305 HASH8( 0,-1, 0, 1), HASH8( 0, 1, 0,-1), HASH8(-1, 0, 1, 0), HASH8( 1, 0,-1, 0),
1306 
1307 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),
1308 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),
1309 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),
1310 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),
1311 
1312 HASH8( 1, 1, 1, 1), HASH8(-1,-1,-1,-1),
1313 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),
1314 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),
1315 };
1316 
1317 #define CHECK_BIDIR(fx,fy,bx,by)\
1318  if( !map[(hashidx+HASH(fx,fy,bx,by))&255]\
1319  &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\
1320  &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\
1321  int score;\
1322  map[(hashidx+HASH(fx,fy,bx,by))&255] = 1;\
1323  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);\
1324  if(score < fbmin){\
1325  hashidx += HASH(fx,fy,bx,by);\
1326  fbmin= score;\
1327  motion_fx+=fx;\
1328  motion_fy+=fy;\
1329  motion_bx+=bx;\
1330  motion_by+=by;\
1331  end=0;\
1332  }\
1333  }
1334 #define CHECK_BIDIR2(a,b,c,d)\
1335 CHECK_BIDIR(a,b,c,d)\
1336 CHECK_BIDIR(-(a),-(b),-(c),-(d))
1337 
1338  do{
1339  int i;
1340  int borderdist=0;
1341  end=1;
1342 
1343  CHECK_BIDIR2(0,0,0,1)
1344  CHECK_BIDIR2(0,0,1,0)
1345  CHECK_BIDIR2(0,1,0,0)
1346  CHECK_BIDIR2(1,0,0,0)
1347 
1348  for(i=8; i<limit; i++){
1349  int fx= motion_fx+vect[i][0];
1350  int fy= motion_fy+vect[i][1];
1351  int bx= motion_bx+vect[i][2];
1352  int by= motion_by+vect[i][3];
1353  if(borderdist<=0){
1354  int a= (xmax - FFMAX(fx,bx))|(FFMIN(fx,bx) - xmin);
1355  int b= (ymax - FFMAX(fy,by))|(FFMIN(fy,by) - ymin);
1356  if((a|b) < 0)
1357  map[(hashidx+hash[i])&255] = 1;
1358  }
1359  if(!map[(hashidx+hash[i])&255]){
1360  int score;
1361  map[(hashidx+hash[i])&255] = 1;
1362  score= check_bidir_mv(s, fx, fy, bx, by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);
1363  if(score < fbmin){
1364  hashidx += hash[i];
1365  fbmin= score;
1366  motion_fx=fx;
1367  motion_fy=fy;
1368  motion_bx=bx;
1369  motion_by=by;
1370  end=0;
1371  borderdist--;
1372  if(borderdist<=0){
1373  int a= FFMIN(xmax - FFMAX(fx,bx), FFMIN(fx,bx) - xmin);
1374  int b= FFMIN(ymax - FFMAX(fy,by), FFMIN(fy,by) - ymin);
1375  borderdist= FFMIN(a,b);
1376  }
1377  }
1378  }
1379  }
1380  }while(!end);
1381  }
1382 
1383  s->b_bidir_forw_mv_table[xy][0]= motion_fx;
1384  s->b_bidir_forw_mv_table[xy][1]= motion_fy;
1385  s->b_bidir_back_mv_table[xy][0]= motion_bx;
1386  s->b_bidir_back_mv_table[xy][1]= motion_by;
1387 
1388  return fbmin;
1389 }
1390 
1391 static inline int direct_search(MPVEncContext *const s, int mb_x, int mb_y)
1392 {
1393  MotionEstContext *const c = &s->me;
1394  int P[10][2];
1395  const int mot_stride = s->c.mb_stride;
1396  const int mot_xy = mb_y*mot_stride + mb_x;
1397  const int shift= 1+s->c.quarter_sample;
1398  int dmin, i;
1399  const int time_pp= s->c.pp_time;
1400  const int time_pb= s->c.pb_time;
1401  int mx, my, xmin, xmax, ymin, ymax;
1402  int16_t (*mv_table)[2]= s->b_direct_mv_table;
1403 
1404  c->current_mv_penalty= c->mv_penalty[1] + MAX_DMV;
1405  ymin= xmin=(-32)>>shift;
1406  ymax= xmax= 31>>shift;
1407 
1408  if (IS_8X8(s->c.next_pic.mb_type[mot_xy])) {
1409  s->c.mv_type = MV_TYPE_8X8;
1410  }else{
1411  s->c.mv_type = MV_TYPE_16X16;
1412  }
1413 
1414  for(i=0; i<4; i++){
1415  int index= s->c.block_index[i];
1416  int min, max;
1417 
1418  c->co_located_mv[i][0] = s->c.next_pic.motion_val[0][index][0];
1419  c->co_located_mv[i][1] = s->c.next_pic.motion_val[0][index][1];
1420  c->direct_basis_mv[i][0]= c->co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3));
1421  c->direct_basis_mv[i][1]= c->co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));
1422 // c->direct_basis_mv[1][i][0]= c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
1423 // c->direct_basis_mv[1][i][1]= c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);
1424 
1425  max= FFMAX(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
1426  min= FFMIN(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
1427  max+= 16*mb_x + 1; // +-1 is for the simpler rounding
1428  min+= 16*mb_x - 1;
1429  xmax= FFMIN(xmax, s->c.width - max);
1430  xmin= FFMAX(xmin, - 16 - min);
1431 
1432  max= FFMAX(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
1433  min= FFMIN(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
1434  max+= 16*mb_y + 1; // +-1 is for the simpler rounding
1435  min+= 16*mb_y - 1;
1436  ymax= FFMIN(ymax, s->c.height - max);
1437  ymin= FFMAX(ymin, - 16 - min);
1438 
1439  if(s->c.mv_type == MV_TYPE_16X16) break;
1440  }
1441 
1442  av_assert2(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16);
1443 
1444  if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){
1445  s->b_direct_mv_table[mot_xy][0]= 0;
1446  s->b_direct_mv_table[mot_xy][1]= 0;
1447 
1448  return 256*256*256*64-1;
1449  }
1450 
1451  c->xmin= xmin;
1452  c->ymin= ymin;
1453  c->xmax= xmax;
1454  c->ymax= ymax;
1455  c->flags |= FLAG_DIRECT;
1456  c->sub_flags |= FLAG_DIRECT;
1457  c->pred_x=0;
1458  c->pred_y=0;
1459 
1460  P_LEFT[0] = av_clip(mv_table[mot_xy - 1][0], xmin * (1 << shift), xmax << shift);
1461  P_LEFT[1] = av_clip(mv_table[mot_xy - 1][1], ymin * (1 << shift), ymax << shift);
1462 
1463  /* special case for first line */
1464  if (!s->c.first_slice_line) { //FIXME maybe allow this over thread boundary as it is clipped
1465  P_TOP[0] = av_clip(mv_table[mot_xy - mot_stride ][0], xmin * (1 << shift), xmax << shift);
1466  P_TOP[1] = av_clip(mv_table[mot_xy - mot_stride ][1], ymin * (1 << shift), ymax << shift);
1467  P_TOPRIGHT[0] = av_clip(mv_table[mot_xy - mot_stride + 1][0], xmin * (1 << shift), xmax << shift);
1468  P_TOPRIGHT[1] = av_clip(mv_table[mot_xy - mot_stride + 1][1], ymin * (1 << shift), ymax << shift);
1469 
1470  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1471  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1472  }
1473 
1474  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, mv_table, 1<<(16-shift), 0, 16);
1475  if(c->sub_flags&FLAG_QPEL)
1476  dmin = qpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1477  else
1478  dmin = hpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1479 
1480  if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1481  dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
1482 
1483  get_limits(s, 16*mb_x, 16*mb_y, 1); //restore c->?min/max, maybe not needed
1484 
1485  mv_table[mot_xy][0]= mx;
1486  mv_table[mot_xy][1]= my;
1487  c->flags &= ~FLAG_DIRECT;
1488  c->sub_flags &= ~FLAG_DIRECT;
1489 
1490  return dmin;
1491 }
1492 
1494  int mb_x, int mb_y)
1495 {
1496  MotionEstContext *const c = &s->me;
1497  int fmin, bmin, dmin, fbmin, bimin, fimin;
1498  int type=0;
1499  const int xy = mb_y*s->c.mb_stride + mb_x;
1500  init_ref(c, s->new_pic->data, s->c.last_pic.data,
1501  s->c.next_pic.data, 16 * mb_x, 16 * mb_y, 2);
1502 
1503  get_limits(s, 16*mb_x, 16*mb_y, 1);
1504 
1505  c->skip=0;
1506 
1507  if (s->c.codec_id == AV_CODEC_ID_MPEG4 && s->c.next_pic.mbskip_table[xy]) {
1508  int score= direct_search(s, mb_x, mb_y); //FIXME just check 0,0
1509 
1510  score= ((unsigned)(score*score + 128*256))>>16;
1511  c->mc_mb_var_sum_temp += score;
1512  s->mc_mb_var[mb_y*s->c.mb_stride + mb_x] = score; //FIXME use SSE
1513  s->mb_type[mb_y*s->c.mb_stride + mb_x]= CANDIDATE_MB_TYPE_DIRECT0;
1514 
1515  return;
1516  }
1517 
1518  c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
1519  c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
1520  c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
1521 
1522  if (s->c.codec_id == AV_CODEC_ID_MPEG4)
1523  dmin= direct_search(s, mb_x, mb_y);
1524  else
1525  dmin= INT_MAX;
1526 
1527 // FIXME penalty stuff for non-MPEG-4
1528  c->skip=0;
1529  fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->c.f_code) +
1530  3 * c->mb_penalty_factor;
1531 
1532  c->skip=0;
1533  bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->c.b_code) +
1534  2 * c->mb_penalty_factor;
1535  ff_dlog(c->avctx, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1536 
1537  c->skip=0;
1538  fbmin= bidir_refine(s, mb_x, mb_y) + c->mb_penalty_factor;
1539  ff_dlog(c->avctx, "%d %d %d %d\n", dmin, fmin, bmin, fbmin);
1540 
1541  if (c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
1542 //FIXME mb type penalty
1543  c->skip=0;
1544  c->current_mv_penalty= c->mv_penalty[s->c.f_code] + MAX_DMV;
1545  fimin= interlaced_search(s, 0,
1546  s->b_field_mv_table[0], s->b_field_select_table[0],
1547  s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0);
1548  c->current_mv_penalty= c->mv_penalty[s->c.b_code] + MAX_DMV;
1549  bimin= interlaced_search(s, 2,
1550  s->b_field_mv_table[1], s->b_field_select_table[1],
1551  s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0);
1552  }else
1553  fimin= bimin= INT_MAX;
1554 
1555  {
1556  int score= fmin;
1558 
1559  if (dmin <= score){
1560  score = dmin;
1562  }
1563  if(bmin<score){
1564  score=bmin;
1566  }
1567  if(fbmin<score){
1568  score=fbmin;
1570  }
1571  if(fimin<score){
1572  score=fimin;
1574  }
1575  if(bimin<score){
1576  score=bimin;
1578  }
1579 
1580  score= ((unsigned)(score*score + 128*256))>>16;
1581  c->mc_mb_var_sum_temp += score;
1582  s->mc_mb_var[mb_y*s->c.mb_stride + mb_x] = score; //FIXME use SSE
1583  }
1584 
1585  if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
1587  if(fimin < INT_MAX)
1589  if(bimin < INT_MAX)
1591  if(fimin < INT_MAX && bimin < INT_MAX){
1593  }
1594  //FIXME something smarter
1595  if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //do not try direct mode if it is invalid for this MB
1596  if (s->c.codec_id == AV_CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT &&
1597  s->mpv_flags & FF_MPV_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy])
1599  }
1600 
1601  s->mb_type[mb_y*s->c.mb_stride + mb_x]= type;
1602 }
1603 
1604 /* find best f_code for ME which do unlimited searches */
1605 int ff_get_best_fcode(MPVMainEncContext *const m, const int16_t (*mv_table)[2], int type)
1606 {
1607  MPVEncContext *const s = &m->s;
1608  MotionEstContext *const c = &s->me;
1609 
1610  if (c->motion_est != FF_ME_ZERO) {
1611  int score[8];
1612  int i, range = c->avctx->me_range ? c->avctx->me_range : (INT_MAX/2);
1613  const uint8_t * fcode_tab = m->fcode_tab;
1614  int best_fcode=-1;
1615  int best_score=-10000000;
1616 
1617  if (s->c.msmpeg4_version != MSMP4_UNUSED)
1618  range= FFMIN(range, 16);
1619  else if (s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO &&
1620  c->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)
1621  range= FFMIN(range, 256);
1622 
1623  for(i=0; i<8; i++) score[i]= s->c.mb_num*(8-i);
1624 
1625  for (int y = 0; y < s->c.mb_height; y++) {
1626  int x;
1627  int xy= y*s->c.mb_stride;
1628  for(x=0; x<s->c.mb_width; x++, xy++){
1629  if(s->mb_type[xy] & type){
1630  int mx= mv_table[xy][0];
1631  int my= mv_table[xy][1];
1632  int fcode = FFMAX(fcode_tab[mx], fcode_tab[my]);
1633  int j;
1634 
1635  if (mx >= range || mx < -range ||
1636  my >= range || my < -range)
1637  continue;
1638 
1639  for(j=0; j<fcode && j<8; j++){
1640  if (s->c.pict_type == AV_PICTURE_TYPE_B ||
1641  s->mc_mb_var[xy] < s->mb_var[xy])
1642  score[j]-= 170;
1643  }
1644  }
1645  }
1646  }
1647 
1648  for(i=1; i<8; i++){
1649  if(score[i] > best_score){
1650  best_score= score[i];
1651  best_fcode= i;
1652  }
1653  }
1654 
1655  return best_fcode;
1656  }else{
1657  return 1;
1658  }
1659 }
1660 
1662 {
1663  MotionEstContext *const c = &s->me;
1664  const int f_code= s->c.f_code;
1665  int y, range;
1666  av_assert0(s->c.pict_type == AV_PICTURE_TYPE_P);
1667 
1668  range = (((s->c.out_format == FMT_MPEG1 || s->c.msmpeg4_version != MSMP4_UNUSED) ? 8 : 16) << f_code);
1669 
1670  av_assert0(range <= 16 || s->c.msmpeg4_version == MSMP4_UNUSED);
1671  av_assert0(range <=256 || !(s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO && c->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL));
1672 
1673  if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
1674 
1675  if (c->avctx->flags & AV_CODEC_FLAG_4MV) {
1676  const int wrap= s->c.b8_stride;
1677 
1678  /* clip / convert to intra 8x8 type MVs */
1679  for(y=0; y<s->c.mb_height; y++){
1680  int xy= y*2*wrap;
1681  int i= y*s->c.mb_stride;
1682  int x;
1683 
1684  for(x=0; x<s->c.mb_width; x++){
1685  if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){
1686  int block;
1687  for(block=0; block<4; block++){
1688  int off= (block& 1) + (block>>1)*wrap;
1689  int mx = s->c.cur_pic.motion_val[0][ xy + off ][0];
1690  int my = s->c.cur_pic.motion_val[0][ xy + off ][1];
1691 
1692  if( mx >=range || mx <-range
1693  || my >=range || my <-range){
1694  s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
1695  s->mb_type[i] |= type;
1696  s->c.cur_pic.mb_type[i] = type;
1697  }
1698  }
1699  }
1700  xy+=2;
1701  i++;
1702  }
1703  }
1704  }
1705 }
1706 
1707 /**
1708  * @param truncate 1 for truncation, 0 for using intra
1709  */
1710 void ff_fix_long_mvs(MPVEncContext *const s, uint8_t *field_select_table, int field_select,
1711  int16_t (*mv_table)[2], int f_code, int type, int truncate)
1712 {
1713  MotionEstContext *const c = &s->me;
1714  int y, h_range, v_range;
1715 
1716  // RAL: 8 in MPEG-1, 16 in MPEG-4
1717  int range = (((s->c.out_format == FMT_MPEG1 || s->c.msmpeg4_version != MSMP4_UNUSED) ? 8 : 16) << f_code);
1718 
1719  if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
1720 
1721  h_range= range;
1722  v_range= field_select_table ? range>>1 : range;
1723 
1724  /* clip / convert to intra 16x16 type MVs */
1725  for(y=0; y<s->c.mb_height; y++){
1726  int x;
1727  int xy= y*s->c.mb_stride;
1728  for(x=0; x<s->c.mb_width; x++){
1729  if (s->mb_type[xy] & type){ // RAL: "type" test added...
1730  if (!field_select_table || field_select_table[xy] == field_select) {
1731  if( mv_table[xy][0] >=h_range || mv_table[xy][0] <-h_range
1732  || mv_table[xy][1] >=v_range || mv_table[xy][1] <-v_range){
1733 
1734  if(truncate){
1735  if (mv_table[xy][0] > h_range-1) mv_table[xy][0]= h_range-1;
1736  else if(mv_table[xy][0] < -h_range ) mv_table[xy][0]= -h_range;
1737  if (mv_table[xy][1] > v_range-1) mv_table[xy][1]= v_range-1;
1738  else if(mv_table[xy][1] < -v_range ) mv_table[xy][1]= -v_range;
1739  }else{
1740  s->mb_type[xy] &= ~type;
1741  s->mb_type[xy] |= CANDIDATE_MB_TYPE_INTRA;
1742  mv_table[xy][0]=
1743  mv_table[xy][1]= 0;
1744  }
1745  }
1746  }
1747  }
1748  xy++;
1749  }
1750  }
1751 }
CHECK_BIDIR2
#define CHECK_BIDIR2(a, b, c, d)
update_map_generation
static unsigned update_map_generation(MotionEstContext *c)
Definition: motion_est.c:55
flags
const SwsFlags flags[]
Definition: swscale.c:61
ff_fix_long_p_mvs
void ff_fix_long_p_mvs(MPVEncContext *const s, int type)
Definition: motion_est.c:1661
ff_fix_long_mvs
void ff_fix_long_mvs(MPVEncContext *const s, uint8_t *field_select_table, int field_select, int16_t(*mv_table)[2], int f_code, int type, int truncate)
Definition: motion_est.c:1710
MPVMainEncContext::fcode_tab
const uint8_t * fcode_tab
smallest fcode needed for each MV
Definition: mpegvideoenc.h:212
IS_8X8
#define IS_8X8(a)
Definition: mpegutils.h:83
CANDIDATE_MB_TYPE_BIDIR
#define CANDIDATE_MB_TYPE_BIDIR
Definition: mpegvideoenc.h:271
MV_TYPE_16X16
#define MV_TYPE_16X16
1 vector for the whole mb
Definition: mpegvideo.h:192
hpel_motion_search
static int hpel_motion_search(MPVEncContext *const s, int *mx_ptr, int *my_ptr, int dmin, int src_index, int ref_index, int size, int h)
Definition: motion_est_template.c:50
ff_estimate_b_frame_motion
void ff_estimate_b_frame_motion(MPVEncContext *const s, int mb_x, int mb_y)
Definition: motion_est.c:1493
av_clip
#define av_clip
Definition: common.h:100
MPVEncContext
Definition: mpegvideoenc.h:45
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
ff_me_init
av_cold int ff_me_init(MotionEstContext *c, AVCodecContext *avctx, const MECmpContext *mecc, int mpvenc)
Definition: motion_est.c:309
MotionEstContext
Motion estimation context.
Definition: motion_est.h:49
estimate_motion_b
static int estimate_motion_b(MPVEncContext *const s, int mb_x, int mb_y, int16_t(*mv_table)[2], int ref_index, int f_code)
Definition: motion_est.c:1120
mpegvideoenc.h
ff_me_init_pic
void ff_me_init_pic(MPVEncContext *const s)
Definition: motion_est.c:371
mask
int mask
Definition: mediacodecdec_common.c:154
AV_CODEC_ID_MPEG4
@ AV_CODEC_ID_MPEG4
Definition: codec_id.h:64
CANDIDATE_MB_TYPE_INTER
#define CANDIDATE_MB_TYPE_INTER
Definition: mpegvideoenc.h:264
MAX_DMV
#define MAX_DMV
Definition: motion_est.h:39
get_mb_score
static int get_mb_score(MPVEncContext *const s, int mx, int my, int src_index, int ref_index, int size, int h, int add_rate)
Definition: motion_est_template.c:165
Minima::height
int height
Definition: motion_est.c:67
b
#define b
Definition: input.c:42
chroma
static av_always_inline void chroma(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:1639
qpel_motion_search
static int qpel_motion_search(MPVEncContext *const s, int *mx_ptr, int *my_ptr, int dmin, int src_index, int ref_index, int size, int h)
Definition: motion_est_template.c:207
mv_penalty
static uint8_t mv_penalty[MAX_FCODE+1][MAX_DMV *2+1]
Definition: h261enc.c:52
max
#define max(a, b)
Definition: cuda_runtime.h:33
AVCodecContext::me_pre_cmp
int me_pre_cmp
motion estimation prepass comparison function
Definition: avcodec.h:909
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
FF_LAMBDA_SHIFT
#define FF_LAMBDA_SHIFT
Definition: avutil.h:225
FMT_H261
@ FMT_H261
Definition: mpegvideo.h:55
minima_cmp
static int minima_cmp(const void *a, const void *b)
Definition: motion_est.c:72
AV_CODEC_FLAG_INTERLACED_ME
#define AV_CODEC_FLAG_INTERLACED_ME
interlaced motion estimation
Definition: avcodec.h:331
mpegutils.h
hash
uint8_t hash[HASH_SIZE]
Definition: movenc.c:58
AV_CODEC_FLAG_4MV
#define AV_CODEC_FLAG_4MV
4 MV per MB allowed / advanced prediction for H.263.
Definition: avcodec.h:217
P_LEFT
#define P_LEFT
Definition: motion_est.c:41
check_bidir_mv
static int check_bidir_mv(MPVEncContext *const s, int motion_fx, int motion_fy, int motion_bx, int motion_by, int pred_fx, int pred_fy, int pred_bx, int pred_by, int size, int h)
Definition: motion_est.c:1179
AVCodecContext::mb_cmp
int mb_cmp
macroblock comparison function (not supported yet)
Definition: avcodec.h:865
CANDIDATE_MB_TYPE_BACKWARD_I
#define CANDIDATE_MB_TYPE_BACKWARD_I
Definition: mpegvideoenc.h:275
AV_CODEC_ID_H261
@ AV_CODEC_ID_H261
Definition: codec_id.h:55
get_flags
static int get_flags(MotionEstContext *c, int direct, int chroma)
Definition: motion_est.c:104
mx
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
Definition: dsp.h:53
set_p_mv_tables
static void set_p_mv_tables(MPVEncContext *const s, int mx, int my, int mv4)
Definition: motion_est.c:518
FMT_MPEG1
@ FMT_MPEG1
Definition: mpegvideo.h:54
wrap
#define wrap(func)
Definition: neontest.h:65
CHECK_SAD_HALF_MV
#define CHECK_SAD_HALF_MV(suffix, x, y)
Definition: motion_est.c:406
P_MEDIAN
#define P_MEDIAN
Definition: motion_est.c:44
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:488
CANDIDATE_MB_TYPE_SKIPPED
#define CANDIDATE_MB_TYPE_SKIPPED
Definition: mpegvideoenc.h:266
interlaced_search
static int interlaced_search(MPVEncContext *const s, int ref_index, int16_t(*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int mx, int my, int user_field_select)
Definition: motion_est.c:749
FF_CMP_CHROMA
#define FF_CMP_CHROMA
Definition: avcodec.h:888
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
motion_est.h
Minima::y
int y
Definition: motion_est.c:68
FF_CMP_SSE
#define FF_CMP_SSE
Definition: avcodec.h:873
ff_sqrt
#define ff_sqrt
Definition: mathops.h:216
CANDIDATE_MB_TYPE_DIRECT
#define CANDIDATE_MB_TYPE_DIRECT
Definition: mpegvideoenc.h:268
CANDIDATE_MB_TYPE_INTER_I
#define CANDIDATE_MB_TYPE_INTER_I
Definition: mpegvideoenc.h:273
bidir_refine
static int bidir_refine(MPVEncContext *const s, int mb_x, int mb_y)
Definition: motion_est.c:1244
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
av_cold
#define av_cold
Definition: attributes.h:90
MAX_MV
#define MAX_MV
Definition: motion_est.h:37
me_cmp_func
int(* me_cmp_func)(MPVEncContext *c, const uint8_t *blk1, const uint8_t *blk2, ptrdiff_t stride, int h)
Definition: me_cmp.h:50
FF_CMP_BIT
#define FF_CMP_BIT
Definition: avcodec.h:877
cmp_direct_inline
static av_always_inline int cmp_direct_inline(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel)
Definition: motion_est.c:110
s
#define s(width, name)
Definition: cbs_vp9.c:198
P_TOP
#define P_TOP
Definition: motion_est.c:42
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
limits.h
cmp_inline
static av_always_inline int cmp_inline(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel, int chroma)
Definition: motion_est.c:182
Minima
Definition: motion_est.c:66
get_penalty_factor
static int get_penalty_factor(int lambda, int lambda2, int type)
Definition: motion_est.c:867
ff_pre_estimate_p_frame_motion
int ff_pre_estimate_p_frame_motion(MPVEncContext *const s, int mb_x, int mb_y)
Definition: motion_est.c:1067
CANDIDATE_MB_TYPE_FORWARD
#define CANDIDATE_MB_TYPE_FORWARD
Definition: mpegvideoenc.h:269
sad_hpel_motion_search
static int sad_hpel_motion_search(MPVEncContext *const s, int *mx_ptr, int *my_ptr, int dmin, int src_index, int ref_index, int size, int h)
Definition: motion_est.c:413
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:441
my
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
Definition: dsp.h:53
FMT_H263
@ FMT_H263
Definition: mpegvideo.h:56
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
if
if(ret)
Definition: filter_design.txt:179
P_TOPRIGHT
#define P_TOPRIGHT
Definition: motion_est.c:43
P_MV1
#define P_MV1
Definition: motion_est.c:45
MECmpContext
Definition: me_cmp.h:55
CANDIDATE_MB_TYPE_FORWARD_I
#define CANDIDATE_MB_TYPE_FORWARD_I
Definition: mpegvideoenc.h:274
NULL
#define NULL
Definition: coverity.c:32
cmp_func
int(* cmp_func)(const void *, const void *)
Definition: vf_palettegen.c:118
init_ref
static void init_ref(MotionEstContext *c, uint8_t *const src[3], uint8_t *const ref[3], uint8_t *const ref2[3], int x, int y, int ref_index)
Definition: motion_est.c:83
CANDIDATE_MB_TYPE_BACKWARD
#define CANDIDATE_MB_TYPE_BACKWARD
Definition: mpegvideoenc.h:270
motion_est_template.c
mathops.h
Minima::x
int x
Definition: motion_est.c:68
ME_MAP_MV_BITS
#define ME_MAP_MV_BITS
Definition: motion_est.c:48
FF_MB_DECISION_SIMPLE
#define FF_MB_DECISION_SIMPLE
uses mb_cmp
Definition: avcodec.h:940
AVCodecContext::me_cmp
int me_cmp
motion estimation comparison function
Definition: avcodec.h:853
FF_CMP_MEDIAN_SAD
#define FF_CMP_MEDIAN_SAD
Definition: avcodec.h:887
ME_MAP_SIZE
#define ME_MAP_SIZE
Definition: motion_est.h:40
MPVMainEncContext
Definition: mpegvideoenc.h:172
index
int index
Definition: gxfenc.c:90
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
mv_tables
static const VLCElem * mv_tables[2]
Definition: msmpeg4dec.c:49
MV_TYPE_8X8
#define MV_TYPE_8X8
4 vectors (H.263, MPEG-4 4MV)
Definition: mpegvideo.h:193
ff_dlog
#define ff_dlog(a,...)
Definition: tableprint_vlc.h:28
AV_CODEC_FLAG_QPEL
#define AV_CODEC_FLAG_QPEL
Use qpel MC.
Definition: avcodec.h:225
init_interlaced_ref
static void init_interlaced_ref(MPVEncContext *const s, int ref_index)
Definition: motion_est.c:735
FF_CMP_PSNR
#define FF_CMP_PSNR
Definition: avcodec.h:876
MECmpContext::sse
me_cmp_func sse[6]
Definition: me_cmp.h:59
P
#define P
shift
static int shift(int a, int b)
Definition: bonk.c:261
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
ff_h263_round_chroma
static int ff_h263_round_chroma(int x)
Definition: h263.h:30
FF_CMP_W53
#define FF_CMP_W53
Definition: avcodec.h:883
direct_search
static int direct_search(MPVEncContext *const s, int mb_x, int mb_y)
Definition: motion_est.c:1391
CANDIDATE_MB_TYPE_DIRECT0
#define CANDIDATE_MB_TYPE_DIRECT0
Definition: mpegvideoenc.h:278
fmin
double fmin(double, double)
size
int size
Definition: twinvq_data.h:10344
CANDIDATE_MB_TYPE_INTRA
#define CANDIDATE_MB_TYPE_INTRA
Definition: mpegvideoenc.h:263
LOAD_COMMON
#define LOAD_COMMON
Definition: motion_est_template.c:31
cmp_internal
static int cmp_internal(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
Definition: motion_est.c:250
range
enum AVColorRange range
Definition: mediacodec_wrapper.c:2594
cmp
static av_always_inline int cmp(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
compares a block (either a full macroblock or a partition thereof) against a proposed motion-compensa...
Definition: motion_est.c:263
ff_set_cmp
av_cold int ff_set_cmp(const MECmpContext *c, me_cmp_func *cmp, int type, int mpvenc)
Fill the function pointer array cmp[6] with me_cmp_funcs from c based upon type.
Definition: me_cmp.c:478
FF_CMP_SATD
#define FF_CMP_SATD
Definition: avcodec.h:874
AVCodecContext::me_sub_cmp
int me_sub_cmp
subpixel motion estimation comparison function
Definition: avcodec.h:859
FF_COMPLIANCE_NORMAL
#define FF_COMPLIANCE_NORMAL
Definition: defs.h:60
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
fcode_tab
static uint8_t fcode_tab[MAX_MV *2+1]
Minimal fcode that a motion vector component would need.
Definition: mpeg4videoenc.c:43
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
HASH8
#define HASH8(fx, fy, bx, by)
FF_CMP_SAD
#define FF_CMP_SAD
Definition: avcodec.h:872
MECmpContext::pix_abs
me_cmp_func pix_abs[2][4]
Definition: me_cmp.h:73
CANDIDATE_MB_TYPE_BIDIR_I
#define CANDIDATE_MB_TYPE_BIDIR_I
Definition: mpegvideoenc.h:276
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:220
CANDIDATE_MB_TYPE_INTER4V
#define CANDIDATE_MB_TYPE_INTER4V
Definition: mpegvideoenc.h:265
cmp_hpel
static int cmp_hpel(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
Definition: motion_est.c:278
mv_scale
static av_always_inline void mv_scale(Mv *dst, const Mv *src, int td, int tb)
Definition: mvs.c:116
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:67
ME_MAP_SHIFT
#define ME_MAP_SHIFT
Definition: motion_est.c:47
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FF_CMP_RD
#define FF_CMP_RD
Definition: avcodec.h:878
av_builtin_constant_p
#define av_builtin_constant_p
Definition: attributes.h:160
init_mv4_ref
static void init_mv4_ref(MotionEstContext *c)
Definition: motion_est.c:581
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:56
av_always_inline
#define av_always_inline
Definition: attributes.h:49
cmp_fpel_internal
static int cmp_fpel_internal(MPVEncContext *const s, const int x, const int y, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
Definition: motion_est.c:240
AVCodecContext::dia_size
int dia_size
ME diamond size & shape.
Definition: avcodec.h:895
cmp_qpel
static int cmp_qpel(MPVEncContext *const s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
Definition: motion_est.c:288
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
FF_CMP_NSSE
#define FF_CMP_NSSE
Definition: avcodec.h:882
MAX_SAB_SIZE
#define MAX_SAB_SIZE
Definition: motion_est_template.c:680
avcodec.h
limit
static double limit(double x)
Definition: vf_pseudocolor.c:142
zero_hpel
static void zero_hpel(uint8_t *a, const uint8_t *b, ptrdiff_t stride, int h)
Definition: motion_est.c:306
stride
#define stride
Definition: h264pred_template.c:536
mid_pred
#define mid_pred
Definition: mathops.h:96
ret
ret
Definition: filter_design.txt:187
FLAG_CHROMA
#define FLAG_CHROMA
Definition: motion_est.c:80
FLAG_QPEL
#define FLAG_QPEL
Definition: motion_est.c:79
AVCodecContext
main external API structure.
Definition: avcodec.h:431
AV_CODEC_ID_SNOW
@ AV_CODEC_ID_SNOW
Definition: codec_id.h:267
AV_PICTURE_TYPE_B
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition: avutil.h:281
cmp_simple
static int cmp_simple(MPVEncContext *const s, const int x, const int y, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func)
Definition: motion_est.c:234
h263_mv4_search
static int h263_mv4_search(MPVEncContext *const s, int mx, int my, int shift)
Definition: motion_est.c:592
FF_CMP_DCT
#define FF_CMP_DCT
Definition: avcodec.h:875
zero_cmp
static int zero_cmp(MPVEncContext *const s, const uint8_t *a, const uint8_t *b, ptrdiff_t stride, int h)
Definition: motion_est.c:300
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
FF_MPV_FLAG_MV0
#define FF_MPV_FLAG_MV0
Definition: mpegvideoenc.h:286
mean
static float mean(const float *input, int size)
Definition: vf_nnedi.c:861
AVCodecContext::pre_dia_size
int pre_dia_size
ME prepass diamond size & shape.
Definition: avcodec.h:916
ff_estimate_p_frame_motion
void ff_estimate_p_frame_motion(MPVEncContext *const s, int mb_x, int mb_y)
Definition: motion_est.c:892
AV_PICTURE_TYPE_P
@ AV_PICTURE_TYPE_P
Predicted.
Definition: avutil.h:280
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
ff_epzs_motion_search
int ff_epzs_motion_search(MPVEncContext *s, int *mx_ptr, int *my_ptr, int P[10][2], int src_index, int ref_index, const int16_t(*last_mv)[2], int ref_mv_scale, int size, int h)
Definition: motion_est_template.c:977
FF_CMP_DCT264
#define FF_CMP_DCT264
Definition: avcodec.h:886
no_sub_motion_search
static int no_sub_motion_search(MPVEncContext *const s, int *mx_ptr, int *my_ptr, int dmin, int src_index, int ref_index, int size, int h)
Definition: motion_est_template.c:155
block
The exact code depends on how similar the blocks are and how related they are to the block
Definition: filter_design.txt:207
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2070
HASH
#define HASH(fx, fy, bx, by)
Minima::checked
int checked
Definition: motion_est.c:69
AV_CODEC_ID_MPEG2VIDEO
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition: codec_id.h:54
MPVMainEncContext::s
MPVEncContext s
The main slicecontext.
Definition: mpegvideoenc.h:173
FLAG_DIRECT
#define FLAG_DIRECT
Definition: motion_est.c:81
src
#define src
Definition: vp8dsp.c:248
get_limits
static void get_limits(MPVEncContext *const s, int x, int y, int bframe)
get fullpel ME search limits.
Definition: motion_est.c:545
epzs_motion_search2
static int epzs_motion_search2(MPVEncContext *const s, int *mx_ptr, int *my_ptr, int P[10][2], int src_index, int ref_index, const int16_t(*last_mv)[2], int ref_mv_scale, const int size)
Definition: motion_est_template.c:993
FF_ME_ZERO
#define FF_ME_ZERO
Definition: motion_est.h:42
FF_CMP_W97
#define FF_CMP_W97
Definition: avcodec.h:884
h263.h
min
float min
Definition: vorbis_enc_data.h:429
ff_get_best_fcode
int ff_get_best_fcode(MPVMainEncContext *const m, const int16_t(*mv_table)[2], int type)
Definition: motion_est.c:1605