FFmpeg
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] ? src[i] + offset[i] : NULL;
95  c->ref[0][i]= ref[i] ? ref[i] + offset[i] : NULL;
96  }
97  if(ref_index){
98  for(i=0; i<3; i++){
99  c->ref[ref_index][i]= ref2[i] ? ref2[i] + offset[i] : NULL;
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) &&
123  y >= c->ymin && hy <= c->ymax << (qpel + 1)) {
124  const int time_pp = s->c.pp_time;
125  const int time_pb = s->c.pb_time;
126  const int mask = 2 * qpel + 1;
127  if (s->c.mv_type == MV_TYPE_8X8) {
128  for(int 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 (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 = 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->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->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] = FFMAX(s->p_mv_table[xy + 1][0], c->xmin * (1 << shift));
1086  P_LEFT[1] = s->p_mv_table[xy + 1][1];
1087 
1088  /* special case for first line */
1089  if (s->c.first_slice_line) {
1090  c->pred_x= P_LEFT[0];
1091  c->pred_y= P_LEFT[1];
1092  P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]=
1093  P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0; //FIXME
1094  } else {
1095  P_TOP[0] = s->p_mv_table[xy + s->c.mb_stride ][0];
1096  P_TOP[1] = s->p_mv_table[xy + s->c.mb_stride ][1];
1097  P_TOPRIGHT[0] = s->p_mv_table[xy + s->c.mb_stride - 1][0];
1098  P_TOPRIGHT[1] = s->p_mv_table[xy + s->c.mb_stride - 1][1];
1099  if(P_TOP[1] < (c->ymin<<shift)) P_TOP[1] = (c->ymin<<shift);
1100  if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
1101  if(P_TOPRIGHT[1] < (c->ymin<<shift)) P_TOPRIGHT[1]= (c->ymin<<shift);
1102 
1103  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1104  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1105 
1106  c->pred_x = P_MEDIAN[0];
1107  c->pred_y = P_MEDIAN[1];
1108  }
1109 
1110  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
1111 
1112  s->p_mv_table[xy][0] = mx<<shift;
1113  s->p_mv_table[xy][1] = my<<shift;
1114 
1115  return dmin;
1116 }
1117 
1118 static int estimate_motion_b(MPVEncContext *const s, int mb_x, int mb_y,
1119  int16_t (*mv_table)[2], int ref_index, int f_code)
1120 {
1121  MotionEstContext *const c = &s->me;
1122  int mx = 0, my = 0, dmin = 0;
1123  int P[10][2];
1124  const int shift= 1+s->c.quarter_sample;
1125  const int mot_stride = s->c.mb_stride;
1126  const int mot_xy = mb_y*mot_stride + mb_x;
1127  const uint8_t * const mv_penalty = c->mv_penalty[f_code] + MAX_DMV;
1128  int mv_scale;
1129 
1130  c->current_mv_penalty= mv_penalty;
1131 
1132  get_limits(s, 16*mb_x, 16*mb_y, 1);
1133 
1134  if (c->motion_est != FF_ME_ZERO) {
1135  P_LEFT[0] = mv_table[mot_xy - 1][0];
1136  P_LEFT[1] = mv_table[mot_xy - 1][1];
1137 
1138  if (P_LEFT[0] > (c->xmax << shift)) P_LEFT[0] = (c->xmax << shift);
1139 
1140  /* special case for first line */
1141  if (!s->c.first_slice_line) {
1142  P_TOP[0] = mv_table[mot_xy - mot_stride ][0];
1143  P_TOP[1] = mv_table[mot_xy - mot_stride ][1];
1144  P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1][0];
1145  P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1][1];
1146  if (P_TOP[1] > (c->ymax << shift)) P_TOP[1] = (c->ymax << shift);
1147  if (P_TOPRIGHT[0] < c->xmin * (1 << shift)) P_TOPRIGHT[0] = c->xmin * (1 << shift);
1148  if (P_TOPRIGHT[1] > (c->ymax << shift)) P_TOPRIGHT[1] = (c->ymax << shift);
1149 
1150  P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1151  P_MEDIAN[1] = mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1152  }
1153  c->pred_x = P_LEFT[0];
1154  c->pred_y = P_LEFT[1];
1155 
1156  if(mv_table == s->b_forw_mv_table){
1157  mv_scale= (s->c.pb_time<<16) / (s->c.pp_time<<shift);
1158  }else{
1159  mv_scale = ((s->c.pb_time - s->c.pp_time) * (1 << 16)) / (s->c.pp_time<<shift);
1160  }
1161 
1162  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->p_mv_table, mv_scale, 0, 16);
1163  }
1164 
1165  dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, ref_index, 0, 16);
1166 
1167  if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1168  dmin= get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1);
1169 
1170 // s->mb_type[mb_y*s->c.mb_width + mb_x]= mb_type;
1171  mv_table[mot_xy][0]= mx;
1172  mv_table[mot_xy][1]= my;
1173 
1174  return dmin;
1175 }
1176 
1177 static inline int check_bidir_mv(MPVEncContext *const s,
1178  int motion_fx, int motion_fy,
1179  int motion_bx, int motion_by,
1180  int pred_fx, int pred_fy,
1181  int pred_bx, int pred_by,
1182  int size, int h)
1183 {
1184  //FIXME optimize?
1185  //FIXME better f_code prediction (max mv & distance)
1186  //FIXME pointers
1187  MotionEstContext *const c = &s->me;
1188  const uint8_t * const mv_penalty_f = c->mv_penalty[s->f_code] + MAX_DMV; // f_code of the prev frame
1189  const uint8_t * const mv_penalty_b = c->mv_penalty[s->b_code] + MAX_DMV; // f_code of the prev frame
1190  int stride= c->stride;
1191  uint8_t *dest_y = c->scratchpad;
1192  const uint8_t *ptr;
1193  int dxy;
1194  int src_x, src_y;
1195  int fbmin;
1196  const uint8_t *const *src_data = c->src[0];
1197  const uint8_t *const *ref_data = c->ref[0];
1198  const uint8_t *const *ref2_data = c->ref[2];
1199 
1200  if(s->c.quarter_sample){
1201  dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
1202  src_x = motion_fx >> 2;
1203  src_y = motion_fy >> 2;
1204 
1205  ptr = ref_data[0] + (src_y * stride) + src_x;
1206  s->c.qdsp.put_qpel_pixels_tab[0][dxy](dest_y, ptr, stride);
1207 
1208  dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
1209  src_x = motion_bx >> 2;
1210  src_y = motion_by >> 2;
1211 
1212  ptr = ref2_data[0] + (src_y * stride) + src_x;
1213  s->c.qdsp.avg_qpel_pixels_tab[size][dxy](dest_y, ptr, stride);
1214  }else{
1215  dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1216  src_x = motion_fx >> 1;
1217  src_y = motion_fy >> 1;
1218 
1219  ptr = ref_data[0] + (src_y * stride) + src_x;
1220  s->c.hdsp.put_pixels_tab[size][dxy](dest_y , ptr , stride, h);
1221 
1222  dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
1223  src_x = motion_bx >> 1;
1224  src_y = motion_by >> 1;
1225 
1226  ptr = ref2_data[0] + (src_y * stride) + src_x;
1227  s->c.hdsp.avg_pixels_tab[size][dxy](dest_y , ptr , stride, h);
1228  }
1229 
1230  fbmin = (mv_penalty_f[motion_fx-pred_fx] + mv_penalty_f[motion_fy-pred_fy])*c->mb_penalty_factor
1231  +(mv_penalty_b[motion_bx-pred_bx] + mv_penalty_b[motion_by-pred_by])*c->mb_penalty_factor
1232  + c->mb_cmp[size](s, src_data[0], dest_y, stride, h); // FIXME new_pic
1233 
1234  if(c->avctx->mb_cmp&FF_CMP_CHROMA){
1235  }
1236  //FIXME CHROMA !!!
1237 
1238  return fbmin;
1239 }
1240 
1241 /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1242 static inline int bidir_refine(MPVEncContext *const s, int mb_x, int mb_y)
1243 {
1244  MotionEstContext *const c = &s->me;
1245  const int mot_stride = s->c.mb_stride;
1246  const int xy = mb_y *mot_stride + mb_x;
1247  int fbmin;
1248  int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
1249  int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
1250  int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
1251  int pred_by= s->b_bidir_back_mv_table[xy-1][1];
1252  int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
1253  int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
1254  int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
1255  int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
1256  const int flags= c->sub_flags;
1257  const int qpel= flags&FLAG_QPEL;
1258  const int shift= 1+qpel;
1259  const int xmin= c->xmin * (1 << shift);
1260  const int ymin= c->ymin * (1 << shift);
1261  const int xmax= c->xmax<<shift;
1262  const int ymax= c->ymax<<shift;
1263 #define HASH(fx,fy,bx,by) ((fx)+17*(fy)+63*(bx)+117*(by))
1264 #define HASH8(fx,fy,bx,by) ((uint8_t)HASH(fx,fy,bx,by))
1265  int hashidx= HASH(motion_fx,motion_fy, motion_bx, motion_by);
1266  uint8_t map[256] = { 0 };
1267 
1268  map[hashidx&255] = 1;
1269 
1270  fbmin= check_bidir_mv(s, motion_fx, motion_fy,
1271  motion_bx, motion_by,
1272  pred_fx, pred_fy,
1273  pred_bx, pred_by,
1274  0, 16);
1275 
1276  if (c->avctx->bidir_refine) {
1277  int end;
1278  static const uint8_t limittab[5]={0,8,32,64,80};
1279  const int limit = limittab[c->avctx->bidir_refine];
1280  static const int8_t vect[][4]={
1281 { 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},
1282 
1283 { 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},
1284 { 0, 1, 0, 1}, { 0,-1, 0,-1}, { 1, 0, 1, 0}, {-1, 0,-1, 0},
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 
1288 { 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},
1289 { 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},
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 
1293 { 1, 1, 1, 1}, {-1,-1,-1,-1},
1294 { 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},
1295 { 1, 1,-1,-1}, {-1,-1, 1, 1}, { 1,-1,-1, 1}, {-1, 1, 1,-1}, { 1,-1, 1,-1}, {-1, 1,-1, 1},
1296  };
1297  static const uint8_t hash[]={
1298 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),
1299 
1300 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),
1301 HASH8( 0, 1, 0, 1), HASH8( 0,-1, 0,-1), HASH8( 1, 0, 1, 0), HASH8(-1, 0,-1, 0),
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 
1305 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),
1306 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),
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 
1310 HASH8( 1, 1, 1, 1), HASH8(-1,-1,-1,-1),
1311 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),
1312 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),
1313 };
1314 
1315 #define CHECK_BIDIR(fx,fy,bx,by)\
1316  if( !map[(hashidx+HASH(fx,fy,bx,by))&255]\
1317  &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\
1318  &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\
1319  int score;\
1320  map[(hashidx+HASH(fx,fy,bx,by))&255] = 1;\
1321  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);\
1322  if(score < fbmin){\
1323  hashidx += HASH(fx,fy,bx,by);\
1324  fbmin= score;\
1325  motion_fx+=fx;\
1326  motion_fy+=fy;\
1327  motion_bx+=bx;\
1328  motion_by+=by;\
1329  end=0;\
1330  }\
1331  }
1332 #define CHECK_BIDIR2(a,b,c,d)\
1333 CHECK_BIDIR(a,b,c,d)\
1334 CHECK_BIDIR(-(a),-(b),-(c),-(d))
1335 
1336  do{
1337  int i;
1338  int borderdist=0;
1339  end=1;
1340 
1341  CHECK_BIDIR2(0,0,0,1)
1342  CHECK_BIDIR2(0,0,1,0)
1343  CHECK_BIDIR2(0,1,0,0)
1344  CHECK_BIDIR2(1,0,0,0)
1345 
1346  for(i=8; i<limit; i++){
1347  int fx= motion_fx+vect[i][0];
1348  int fy= motion_fy+vect[i][1];
1349  int bx= motion_bx+vect[i][2];
1350  int by= motion_by+vect[i][3];
1351  if(borderdist<=0){
1352  int a= (xmax - FFMAX(fx,bx))|(FFMIN(fx,bx) - xmin);
1353  int b= (ymax - FFMAX(fy,by))|(FFMIN(fy,by) - ymin);
1354  if((a|b) < 0)
1355  map[(hashidx+hash[i])&255] = 1;
1356  }
1357  if(!map[(hashidx+hash[i])&255]){
1358  int score;
1359  map[(hashidx+hash[i])&255] = 1;
1360  score= check_bidir_mv(s, fx, fy, bx, by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);
1361  if(score < fbmin){
1362  hashidx += hash[i];
1363  fbmin= score;
1364  motion_fx=fx;
1365  motion_fy=fy;
1366  motion_bx=bx;
1367  motion_by=by;
1368  end=0;
1369  borderdist--;
1370  if(borderdist<=0){
1371  int a= FFMIN(xmax - FFMAX(fx,bx), FFMIN(fx,bx) - xmin);
1372  int b= FFMIN(ymax - FFMAX(fy,by), FFMIN(fy,by) - ymin);
1373  borderdist= FFMIN(a,b);
1374  }
1375  }
1376  }
1377  }
1378  }while(!end);
1379  }
1380 
1381  s->b_bidir_forw_mv_table[xy][0]= motion_fx;
1382  s->b_bidir_forw_mv_table[xy][1]= motion_fy;
1383  s->b_bidir_back_mv_table[xy][0]= motion_bx;
1384  s->b_bidir_back_mv_table[xy][1]= motion_by;
1385 
1386  return fbmin;
1387 }
1388 
1389 static inline int direct_search(MPVEncContext *const s, int mb_x, int mb_y)
1390 {
1391  MotionEstContext *const c = &s->me;
1392  int P[10][2];
1393  const int mot_stride = s->c.mb_stride;
1394  const int mot_xy = mb_y*mot_stride + mb_x;
1395  const int shift= 1+s->c.quarter_sample;
1396  int dmin, i;
1397  const int time_pp= s->c.pp_time;
1398  const int time_pb= s->c.pb_time;
1399  int mx, my, xmin, xmax, ymin, ymax;
1400  int16_t (*mv_table)[2]= s->b_direct_mv_table;
1401 
1402  c->current_mv_penalty= c->mv_penalty[1] + MAX_DMV;
1403  ymin= xmin=(-32)>>shift;
1404  ymax= xmax= 31>>shift;
1405 
1406  if (IS_8X8(s->c.next_pic.mb_type[mot_xy])) {
1407  s->c.mv_type = MV_TYPE_8X8;
1408  }else{
1409  s->c.mv_type = MV_TYPE_16X16;
1410  }
1411 
1412  for(i=0; i<4; i++){
1413  int index= s->c.block_index[i];
1414  int min, max;
1415 
1416  c->co_located_mv[i][0] = s->c.next_pic.motion_val[0][index][0];
1417  c->co_located_mv[i][1] = s->c.next_pic.motion_val[0][index][1];
1418  c->direct_basis_mv[i][0]= c->co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3));
1419  c->direct_basis_mv[i][1]= c->co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));
1420 // c->direct_basis_mv[1][i][0]= c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
1421 // c->direct_basis_mv[1][i][1]= c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);
1422 
1423  max= FFMAX(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
1424  min= FFMIN(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
1425  max+= 16*mb_x + 1; // +-1 is for the simpler rounding
1426  min+= 16*mb_x - 1;
1427  xmax= FFMIN(xmax, s->c.width - max);
1428  xmin= FFMAX(xmin, - 16 - min);
1429 
1430  max= FFMAX(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
1431  min= FFMIN(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
1432  max+= 16*mb_y + 1; // +-1 is for the simpler rounding
1433  min+= 16*mb_y - 1;
1434  ymax= FFMIN(ymax, s->c.height - max);
1435  ymin= FFMAX(ymin, - 16 - min);
1436 
1437  if(s->c.mv_type == MV_TYPE_16X16) break;
1438  }
1439 
1440  av_assert2(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16);
1441 
1442  if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){
1443  s->b_direct_mv_table[mot_xy][0]= 0;
1444  s->b_direct_mv_table[mot_xy][1]= 0;
1445 
1446  return 256*256*256*64-1;
1447  }
1448 
1449  c->xmin= xmin;
1450  c->ymin= ymin;
1451  c->xmax= xmax;
1452  c->ymax= ymax;
1453  c->flags |= FLAG_DIRECT;
1454  c->sub_flags |= FLAG_DIRECT;
1455  c->pred_x=0;
1456  c->pred_y=0;
1457 
1458  P_LEFT[0] = av_clip(mv_table[mot_xy - 1][0], xmin * (1 << shift), xmax << shift);
1459  P_LEFT[1] = av_clip(mv_table[mot_xy - 1][1], ymin * (1 << shift), ymax << shift);
1460 
1461  /* special case for first line */
1462  if (!s->c.first_slice_line) { //FIXME maybe allow this over thread boundary as it is clipped
1463  P_TOP[0] = av_clip(mv_table[mot_xy - mot_stride ][0], xmin * (1 << shift), xmax << shift);
1464  P_TOP[1] = av_clip(mv_table[mot_xy - mot_stride ][1], ymin * (1 << shift), ymax << shift);
1465  P_TOPRIGHT[0] = av_clip(mv_table[mot_xy - mot_stride + 1][0], xmin * (1 << shift), xmax << shift);
1466  P_TOPRIGHT[1] = av_clip(mv_table[mot_xy - mot_stride + 1][1], ymin * (1 << shift), ymax << shift);
1467 
1468  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1469  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1470  }
1471 
1472  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, mv_table, 1<<(16-shift), 0, 16);
1473  if(c->sub_flags&FLAG_QPEL)
1474  dmin = qpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1475  else
1476  dmin = hpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1477 
1478  if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1479  dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
1480 
1481  get_limits(s, 16*mb_x, 16*mb_y, 1); //restore c->?min/max, maybe not needed
1482 
1483  mv_table[mot_xy][0]= mx;
1484  mv_table[mot_xy][1]= my;
1485  c->flags &= ~FLAG_DIRECT;
1486  c->sub_flags &= ~FLAG_DIRECT;
1487 
1488  return dmin;
1489 }
1490 
1492  int mb_x, int mb_y)
1493 {
1494  MotionEstContext *const c = &s->me;
1495  int fmin, bmin, dmin, fbmin, bimin, fimin;
1496  int type=0;
1497  const int xy = mb_y*s->c.mb_stride + mb_x;
1498  init_ref(c, s->new_pic->data, s->c.last_pic.data,
1499  s->c.next_pic.data, 16 * mb_x, 16 * mb_y, 2);
1500 
1501  get_limits(s, 16*mb_x, 16*mb_y, 1);
1502 
1503  c->skip=0;
1504 
1505  if (s->c.codec_id == AV_CODEC_ID_MPEG4 && s->c.next_pic.mbskip_table[xy]) {
1506  int score= direct_search(s, mb_x, mb_y); //FIXME just check 0,0
1507 
1508  score= ((unsigned)(score*score + 128*256))>>16;
1509  c->mc_mb_var_sum_temp += score;
1510  s->mc_mb_var[mb_y*s->c.mb_stride + mb_x] = score; //FIXME use SSE
1511  s->mb_type[mb_y*s->c.mb_stride + mb_x]= CANDIDATE_MB_TYPE_DIRECT0;
1512 
1513  return;
1514  }
1515 
1516  c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
1517  c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
1518  c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
1519 
1520  if (s->c.codec_id == AV_CODEC_ID_MPEG4)
1521  dmin= direct_search(s, mb_x, mb_y);
1522  else
1523  dmin= INT_MAX;
1524 
1525 // FIXME penalty stuff for non-MPEG-4
1526  c->skip=0;
1527  fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) +
1528  3 * c->mb_penalty_factor;
1529 
1530  c->skip=0;
1531  bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) +
1532  2 * c->mb_penalty_factor;
1533  ff_dlog(c->avctx, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1534 
1535  c->skip=0;
1536  fbmin= bidir_refine(s, mb_x, mb_y) + c->mb_penalty_factor;
1537  ff_dlog(c->avctx, "%d %d %d %d\n", dmin, fmin, bmin, fbmin);
1538 
1539  if (c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
1540 //FIXME mb type penalty
1541  c->skip=0;
1542  c->current_mv_penalty = c->mv_penalty[s->f_code] + MAX_DMV;
1543  fimin= interlaced_search(s, 0,
1544  s->b_field_mv_table[0], s->b_field_select_table[0],
1545  s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0);
1546  c->current_mv_penalty = c->mv_penalty[s->b_code] + MAX_DMV;
1547  bimin= interlaced_search(s, 2,
1548  s->b_field_mv_table[1], s->b_field_select_table[1],
1549  s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0);
1550  }else
1551  fimin= bimin= INT_MAX;
1552 
1553  {
1554  int score= fmin;
1556 
1557  if (dmin <= score){
1558  score = dmin;
1560  }
1561  if(bmin<score){
1562  score=bmin;
1564  }
1565  if(fbmin<score){
1566  score=fbmin;
1568  }
1569  if(fimin<score){
1570  score=fimin;
1572  }
1573  if(bimin<score){
1574  score=bimin;
1576  }
1577 
1578  score= ((unsigned)(score*score + 128*256))>>16;
1579  c->mc_mb_var_sum_temp += score;
1580  s->mc_mb_var[mb_y*s->c.mb_stride + mb_x] = score; //FIXME use SSE
1581  }
1582 
1583  if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
1585  if(fimin < INT_MAX)
1587  if(bimin < INT_MAX)
1589  if(fimin < INT_MAX && bimin < INT_MAX){
1591  }
1592  //FIXME something smarter
1593  if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //do not try direct mode if it is invalid for this MB
1594  if (s->c.codec_id == AV_CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT &&
1595  s->mpv_flags & FF_MPV_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy])
1597  }
1598 
1599  s->mb_type[mb_y*s->c.mb_stride + mb_x]= type;
1600 }
1601 
1602 /* find best f_code for ME which do unlimited searches */
1603 int ff_get_best_fcode(MPVMainEncContext *const m, const int16_t (*mv_table)[2], int type)
1604 {
1605  MPVEncContext *const s = &m->s;
1606  MotionEstContext *const c = &s->me;
1607 
1608  if (c->motion_est != FF_ME_ZERO) {
1609  int score[8];
1610  int i, range = c->avctx->me_range ? c->avctx->me_range : (INT_MAX/2);
1611  const uint8_t * fcode_tab = m->fcode_tab;
1612  int best_fcode=-1;
1613  int best_score=-10000000;
1614 
1615  if (s->c.msmpeg4_version != MSMP4_UNUSED)
1616  range= FFMIN(range, 16);
1617  else if (s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO &&
1618  c->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)
1619  range= FFMIN(range, 256);
1620 
1621  for(i=0; i<8; i++) score[i]= s->c.mb_num*(8-i);
1622 
1623  for (int y = 0; y < s->c.mb_height; y++) {
1624  int x;
1625  int xy= y*s->c.mb_stride;
1626  for(x=0; x<s->c.mb_width; x++, xy++){
1627  if(s->mb_type[xy] & type){
1628  int mx= mv_table[xy][0];
1629  int my= mv_table[xy][1];
1630  int fcode = FFMAX(fcode_tab[mx], fcode_tab[my]);
1631  int j;
1632 
1633  if (mx >= range || mx < -range ||
1634  my >= range || my < -range)
1635  continue;
1636 
1637  for(j=0; j<fcode && j<8; j++){
1638  if (s->c.pict_type == AV_PICTURE_TYPE_B ||
1639  s->mc_mb_var[xy] < s->mb_var[xy])
1640  score[j]-= 170;
1641  }
1642  }
1643  }
1644  }
1645 
1646  for(i=1; i<8; i++){
1647  if(score[i] > best_score){
1648  best_score= score[i];
1649  best_fcode= i;
1650  }
1651  }
1652 
1653  return best_fcode;
1654  }else{
1655  return 1;
1656  }
1657 }
1658 
1660 {
1661  MotionEstContext *const c = &s->me;
1662  const int f_code= s->f_code;
1663  int y, range;
1664  av_assert0(s->c.pict_type == AV_PICTURE_TYPE_P);
1665 
1666  range = (((s->c.out_format == FMT_MPEG1 || s->c.msmpeg4_version != MSMP4_UNUSED) ? 8 : 16) << f_code);
1667 
1668  av_assert0(range <= 16 || s->c.msmpeg4_version == MSMP4_UNUSED);
1669  av_assert0(range <=256 || !(s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO && c->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL));
1670 
1671  if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
1672 
1673  if (c->avctx->flags & AV_CODEC_FLAG_4MV) {
1674  const int wrap= s->c.b8_stride;
1675 
1676  /* clip / convert to intra 8x8 type MVs */
1677  for(y=0; y<s->c.mb_height; y++){
1678  int xy= y*2*wrap;
1679  int i= y*s->c.mb_stride;
1680  int x;
1681 
1682  for(x=0; x<s->c.mb_width; x++){
1683  if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){
1684  int block;
1685  for(block=0; block<4; block++){
1686  int off= (block& 1) + (block>>1)*wrap;
1687  int mx = s->c.cur_pic.motion_val[0][ xy + off ][0];
1688  int my = s->c.cur_pic.motion_val[0][ xy + off ][1];
1689 
1690  if( mx >=range || mx <-range
1691  || my >=range || my <-range){
1692  s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
1693  s->mb_type[i] |= type;
1694  s->c.cur_pic.mb_type[i] = type;
1695  }
1696  }
1697  }
1698  xy+=2;
1699  i++;
1700  }
1701  }
1702  }
1703 }
1704 
1705 /**
1706  * @param truncate 1 for truncation, 0 for using intra
1707  */
1708 void ff_fix_long_mvs(MPVEncContext *const s, uint8_t *field_select_table, int field_select,
1709  int16_t (*mv_table)[2], int f_code, int type, int truncate)
1710 {
1711  MotionEstContext *const c = &s->me;
1712  int y, h_range, v_range;
1713 
1714  // RAL: 8 in MPEG-1, 16 in MPEG-4
1715  int range = (((s->c.out_format == FMT_MPEG1 || s->c.msmpeg4_version != MSMP4_UNUSED) ? 8 : 16) << f_code);
1716 
1717  if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
1718 
1719  h_range= range;
1720  v_range= field_select_table ? range>>1 : range;
1721 
1722  /* clip / convert to intra 16x16 type MVs */
1723  for(y=0; y<s->c.mb_height; y++){
1724  int x;
1725  int xy= y*s->c.mb_stride;
1726  for(x=0; x<s->c.mb_width; x++){
1727  if (s->mb_type[xy] & type){ // RAL: "type" test added...
1728  if (!field_select_table || field_select_table[xy] == field_select) {
1729  if( mv_table[xy][0] >=h_range || mv_table[xy][0] <-h_range
1730  || mv_table[xy][1] >=v_range || mv_table[xy][1] <-v_range){
1731 
1732  if(truncate){
1733  if (mv_table[xy][0] > h_range-1) mv_table[xy][0]= h_range-1;
1734  else if(mv_table[xy][0] < -h_range ) mv_table[xy][0]= -h_range;
1735  if (mv_table[xy][1] > v_range-1) mv_table[xy][1]= v_range-1;
1736  else if(mv_table[xy][1] < -v_range ) mv_table[xy][1]= -v_range;
1737  }else{
1738  s->mb_type[xy] &= ~type;
1739  s->mb_type[xy] |= CANDIDATE_MB_TYPE_INTRA;
1740  mv_table[xy][0]=
1741  mv_table[xy][1]= 0;
1742  }
1743  }
1744  }
1745  }
1746  xy++;
1747  }
1748  }
1749 }
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:1659
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:1708
MPVMainEncContext::fcode_tab
const uint8_t * fcode_tab
smallest fcode needed for each MV
Definition: mpegvideoenc.h:242
IS_8X8
#define IS_8X8(a)
Definition: mpegutils.h:83
CANDIDATE_MB_TYPE_BIDIR
#define CANDIDATE_MB_TYPE_BIDIR
Definition: mpegvideoenc.h:301
MV_TYPE_16X16
#define MV_TYPE_16X16
1 vector for the whole mb
Definition: mpegvideo.h:172
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:1491
av_clip
#define av_clip
Definition: common.h:100
MPVEncContext
Definition: mpegvideoenc.h:46
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:1118
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:294
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:53
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:914
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
FF_LAMBDA_SHIFT
#define FF_LAMBDA_SHIFT
Definition: avutil.h:224
FMT_H261
@ FMT_H261
Definition: mpegvideo.h:56
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
pix
enum AVPixelFormat pix
Definition: ohcodec.c:55
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:1177
AVCodecContext::mb_cmp
int mb_cmp
macroblock comparison function (not supported yet)
Definition: avcodec.h:870
CANDIDATE_MB_TYPE_BACKWARD_I
#define CANDIDATE_MB_TYPE_BACKWARD_I
Definition: mpegvideoenc.h:305
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:57
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:55
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:496
CANDIDATE_MB_TYPE_SKIPPED
#define CANDIDATE_MB_TYPE_SKIPPED
Definition: mpegvideoenc.h:296
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:893
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:878
ff_sqrt
#define ff_sqrt
Definition: mathops.h:220
CANDIDATE_MB_TYPE_DIRECT
#define CANDIDATE_MB_TYPE_DIRECT
Definition: mpegvideoenc.h:298
CANDIDATE_MB_TYPE_INTER_I
#define CANDIDATE_MB_TYPE_INTER_I
Definition: mpegvideoenc.h:303
bidir_refine
static int bidir_refine(MPVEncContext *const s, int mb_x, int mb_y)
Definition: motion_est.c:1242
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:106
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:45
FF_CMP_BIT
#define FF_CMP_BIT
Definition: avcodec.h:882
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:41
P
#define P
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:299
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:449
my
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
Definition: dsp.h:57
FMT_H263
@ FMT_H263
Definition: mpegvideo.h:57
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:50
CANDIDATE_MB_TYPE_FORWARD_I
#define CANDIDATE_MB_TYPE_FORWARD_I
Definition: mpegvideoenc.h:304
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:300
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:945
AVCodecContext::me_cmp
int me_cmp
motion estimation comparison function
Definition: avcodec.h:858
FF_CMP_MEDIAN_SAD
#define FF_CMP_MEDIAN_SAD
Definition: avcodec.h:892
ME_MAP_SIZE
#define ME_MAP_SIZE
Definition: motion_est.h:40
MPVMainEncContext
Definition: mpegvideoenc.h:202
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:173
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:881
MECmpContext::sse
me_cmp_func sse[6]
Definition: me_cmp.h:54
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:87
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:888
direct_search
static int direct_search(MPVEncContext *const s, int mb_x, int mb_y)
Definition: motion_est.c:1389
CANDIDATE_MB_TYPE_DIRECT0
#define CANDIDATE_MB_TYPE_DIRECT0
Definition: mpegvideoenc.h:308
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:293
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:443
FF_CMP_SATD
#define FF_CMP_SATD
Definition: avcodec.h:879
AVCodecContext::me_sub_cmp
int me_sub_cmp
subpixel motion estimation comparison function
Definition: avcodec.h:864
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:45
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:877
MECmpContext::pix_abs
me_cmp_func pix_abs[2][4]
Definition: me_cmp.h:68
CANDIDATE_MB_TYPE_BIDIR_I
#define CANDIDATE_MB_TYPE_BIDIR_I
Definition: mpegvideoenc.h:306
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
CANDIDATE_MB_TYPE_INTER4V
#define CANDIDATE_MB_TYPE_INTER4V
Definition: mpegvideoenc.h:295
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:68
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:883
av_builtin_constant_p
#define av_builtin_constant_p
Definition: attributes.h:180
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:57
av_always_inline
#define av_always_inline
Definition: attributes.h:63
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:900
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:887
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
mid_pred
#define mid_pred
Definition: mathops.h:115
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:439
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:280
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:880
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:316
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:921
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:279
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:891
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
stride
#define stride
Definition: h264pred_template.c:536
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:203
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:889
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:1603