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 mx_chroma = ff_h263_round_chroma(mx4_sum);
706  int my_chroma = ff_h263_round_chroma(my4_sum);
707  int dxy = ((my_chroma & 1) << 1) | (mx_chroma & 1);
708 
709  int offset = (s->c.mb_x*8 + (mx_chroma>>1)) + (s->c.mb_y*8 + (my_chroma>>1))*s->c.uvlinesize;
710 
711  c->hpel_put[1][dxy](c->scratchpad , s->c.last_pic.data[1] + offset, s->c.uvlinesize, 8);
712  c->hpel_put[1][dxy](c->scratchpad + 8, s->c.last_pic.data[2] + offset, s->c.uvlinesize, 8);
713 
714  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);
715  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);
716  }
717 
718  c->pred_x= mx;
719  c->pred_y= my;
720 
721  switch(c->avctx->mb_cmp&0xFF){
722  /*case FF_CMP_SSE:
723  return dmin_sum+ 32*s->c.qscale*s->c.qscale;*/
724  case FF_CMP_RD:
725  return dmin_sum;
726  default:
727  return dmin_sum+ 11*c->mb_penalty_factor;
728  }
729 }
730 
731 static inline void init_interlaced_ref(MPVEncContext *const s, int ref_index)
732 {
733  MotionEstContext *const c = &s->me;
734 
735  c->ref[1+ref_index][0] = c->ref[0+ref_index][0] + s->c.linesize;
736  c->src[1][0] = c->src[0][0] + s->c.linesize;
737  if(c->flags & FLAG_CHROMA){
738  c->ref[1+ref_index][1] = c->ref[0+ref_index][1] + s->c.uvlinesize;
739  c->ref[1+ref_index][2] = c->ref[0+ref_index][2] + s->c.uvlinesize;
740  c->src[1][1] = c->src[0][1] + s->c.uvlinesize;
741  c->src[1][2] = c->src[0][2] + s->c.uvlinesize;
742  }
743 }
744 
745 static int interlaced_search(MPVEncContext *const s, int ref_index,
746  int16_t (*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int mx, int my, int user_field_select)
747 {
748  MotionEstContext *const c = &s->me;
749  const int size=0;
750  const int h=8;
751  int block;
752  int P[10][2];
753  const uint8_t * const mv_penalty = c->current_mv_penalty;
754  int same=1;
755  const int stride = 2*s->c.linesize;
756  int dmin_sum= 0;
757  const int mot_stride = s->c.mb_stride;
758  const int xy = s->c.mb_x + s->c.mb_y*mot_stride;
759 
760  c->ymin>>=1;
761  c->ymax>>=1;
762  c->stride<<=1;
763  c->uvstride<<=1;
764  init_interlaced_ref(s, ref_index);
765 
766  for(block=0; block<2; block++){
767  int field_select;
768  int best_dmin= INT_MAX;
769  int best_field= -1;
770 
771  for(field_select=0; field_select<2; field_select++){
772  int dmin, mx_i, my_i;
773  int16_t (*mv_table)[2]= mv_tables[block][field_select];
774 
775  if(user_field_select){
776  av_assert1(field_select==0 || field_select==1);
777  av_assert1(field_select_tables[block][xy]==0 || field_select_tables[block][xy]==1);
778  if(field_select_tables[block][xy] != field_select)
779  continue;
780  }
781 
782  P_LEFT[0] = mv_table[xy - 1][0];
783  P_LEFT[1] = mv_table[xy - 1][1];
784  if(P_LEFT[0] > (c->xmax<<1)) P_LEFT[0] = (c->xmax<<1);
785 
786  c->pred_x= P_LEFT[0];
787  c->pred_y= P_LEFT[1];
788 
789  if (!s->c.first_slice_line) {
790  P_TOP[0] = mv_table[xy - mot_stride][0];
791  P_TOP[1] = mv_table[xy - mot_stride][1];
792  P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0];
793  P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1];
794  if(P_TOP[1] > (c->ymax<<1)) P_TOP[1] = (c->ymax<<1);
795  if (P_TOPRIGHT[0] < c->xmin * (1 << 1)) P_TOPRIGHT[0] = c->xmin * (1 << 1);
796  if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1);
797  if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1);
798 
799  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
800  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
801  }
802  P_MV1[0]= mx; //FIXME not correct if block != field_select
803  P_MV1[1]= my / 2;
804 
805  dmin = epzs_motion_search2(s, &mx_i, &my_i, P, block, field_select+ref_index, mv_table, (1<<16)>>1, 0);
806 
807  dmin= c->sub_motion_search(s, &mx_i, &my_i, dmin, block, field_select+ref_index, size, h);
808 
809  mv_table[xy][0]= mx_i;
810  mv_table[xy][1]= my_i;
811 
812  if (c->me_sub_cmp[0] != c->mb_cmp[0]) {
813  int dxy;
814 
815  //FIXME chroma ME
816  const uint8_t *ref = c->ref[field_select+ref_index][0] + (mx_i>>1) + (my_i>>1)*stride;
817  dxy = ((my_i & 1) << 1) | (mx_i & 1);
818 
819  c->hpel_put[size][dxy](c->scratchpad, ref, stride, h);
820  dmin = c->mb_cmp[size](s, c->src[block][0], c->scratchpad, stride, h);
821  dmin+= (mv_penalty[mx_i-c->pred_x] + mv_penalty[my_i-c->pred_y] + 1)*c->mb_penalty_factor;
822  }else
823  dmin+= c->mb_penalty_factor; //field_select bits
824 
825  dmin += field_select != block; //slightly prefer same field
826 
827  if(dmin < best_dmin){
828  best_dmin= dmin;
829  best_field= field_select;
830  }
831  }
832  {
833  int16_t (*mv_table)[2]= mv_tables[block][best_field];
834 
835  if(mv_table[xy][0] != mx) same=0; //FIXME check if these checks work and are any good at all
836  if(mv_table[xy][1]&1) same=0;
837  if(mv_table[xy][1]*2 != my) same=0;
838  if(best_field != block) same=0;
839  }
840 
841  field_select_tables[block][xy]= best_field;
842  dmin_sum += best_dmin;
843  }
844 
845  c->ymin *= 2;
846  c->ymax<<=1;
847  c->stride>>=1;
848  c->uvstride>>=1;
849 
850  if(same)
851  return INT_MAX;
852 
853  switch(c->avctx->mb_cmp&0xFF){
854  /*case FF_CMP_SSE:
855  return dmin_sum+ 32*s->c.qscale*s->c.qscale;*/
856  case FF_CMP_RD:
857  return dmin_sum;
858  default:
859  return dmin_sum+ 11*c->mb_penalty_factor;
860  }
861 }
862 
863 static inline int get_penalty_factor(int lambda, int lambda2, int type){
864  switch(type&0xFF){
865  default:
866  case FF_CMP_SAD:
867  return lambda>>FF_LAMBDA_SHIFT;
868  case FF_CMP_DCT:
869  return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
870  case FF_CMP_W53:
871  return (4*lambda)>>(FF_LAMBDA_SHIFT);
872  case FF_CMP_W97:
873  return (2*lambda)>>(FF_LAMBDA_SHIFT);
874  case FF_CMP_SATD:
875  case FF_CMP_DCT264:
876  return (2*lambda)>>FF_LAMBDA_SHIFT;
877  case FF_CMP_RD:
878  case FF_CMP_PSNR:
879  case FF_CMP_SSE:
880  case FF_CMP_NSSE:
881  return lambda2>>FF_LAMBDA_SHIFT;
882  case FF_CMP_BIT:
883  case FF_CMP_MEDIAN_SAD:
884  return 1;
885  }
886 }
887 
889  int mb_x, int mb_y)
890 {
891  MotionEstContext *const c = &s->me;
892  const uint8_t *pix, *ppix;
893  int sum, mx = 0, my = 0, dmin = 0;
894  int varc; ///< the variance of the block (sum of squared (p[y][x]-average))
895  int vard; ///< sum of squared differences with the estimated motion vector
896  int P[10][2];
897  const int shift = 1 + s->c.quarter_sample;
898  int mb_type=0;
899 
900  init_ref(c, s->new_pic->data, s->c.last_pic.data, NULL, 16*mb_x, 16*mb_y, 0);
901 
902  av_assert0(s->c.quarter_sample == 0 || s->c.quarter_sample == 1);
903  av_assert0(s->c.linesize == c->stride);
904  av_assert0(s->c.uvlinesize == c->uvstride);
905 
906  c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
907  c->sub_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
908  c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
909  c->current_mv_penalty = c->mv_penalty[s->f_code] + MAX_DMV;
910 
911  get_limits(s, 16*mb_x, 16*mb_y, 0);
912  c->skip=0;
913 
914  /* intra / predictive decision */
915  pix = c->src[0][0];
916  sum = s->mpvencdsp.pix_sum(pix, s->c.linesize);
917  varc = s->mpvencdsp.pix_norm1(pix, s->c.linesize) -
918  (((unsigned) sum * sum) >> 8) + 500;
919 
920  s->mb_mean[s->c.mb_stride * mb_y + mb_x] = (sum + 128) >> 8;
921  s->mb_var [s->c.mb_stride * mb_y + mb_x] = (varc + 128) >> 8;
922  c->mb_var_sum_temp += (varc+128)>>8;
923 
924  if (c->motion_est != FF_ME_ZERO) {
925  const int mot_stride = s->c.b8_stride;
926  const int mot_xy = s->c.block_index[0];
927 
928  P_LEFT[0] = s->c.cur_pic.motion_val[0][mot_xy - 1][0];
929  P_LEFT[1] = s->c.cur_pic.motion_val[0][mot_xy - 1][1];
930 
931  if (P_LEFT[0] > (c->xmax << shift))
932  P_LEFT[0] = c->xmax << shift;
933 
934  if (!s->c.first_slice_line) {
935  P_TOP[0] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride ][0];
936  P_TOP[1] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride ][1];
937  P_TOPRIGHT[0] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride + 2][0];
938  P_TOPRIGHT[1] = s->c.cur_pic.motion_val[0][mot_xy - mot_stride + 2][1];
939  if (P_TOP[1] > (c->ymax << shift))
940  P_TOP[1] = c->ymax << shift;
941  if (P_TOPRIGHT[0] < (c->xmin * (1 << shift)))
942  P_TOPRIGHT[0] = c->xmin * (1 << shift);
943  if (P_TOPRIGHT[1] > (c->ymax * (1 << shift)))
944  P_TOPRIGHT[1] = c->ymax * (1 << shift);
945 
946  P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
947  P_MEDIAN[1] = mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
948 
949  if (s->c.out_format == FMT_H263) {
950  c->pred_x = P_MEDIAN[0];
951  c->pred_y = P_MEDIAN[1];
952  } else { /* MPEG-1 at least */
953  c->pred_x = P_LEFT[0];
954  c->pred_y = P_LEFT[1];
955  }
956  } else {
957  c->pred_x = P_LEFT[0];
958  c->pred_y = P_LEFT[1];
959  }
960  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
961  }
962 
963  /* At this point (mx,my) are full-pell and the relative displacement */
964  ppix = c->ref[0][0] + (my * s->c.linesize) + mx;
965 
966  vard = c->sse(NULL, pix, ppix, s->c.linesize, 16);
967 
968  s->mc_mb_var[s->c.mb_stride * mb_y + mb_x] = (vard+128)>>8;
969  c->mc_mb_var_sum_temp += (vard+128)>>8;
970 
971  if (c->avctx->mb_decision > FF_MB_DECISION_SIMPLE) {
972  int p_score = FFMIN(vard, varc - 500 + (s->lambda2 >> FF_LAMBDA_SHIFT)*100);
973  int i_score = varc - 500 + (s->lambda2 >> FF_LAMBDA_SHIFT)*20;
974  c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
975 
976  if (vard*2 + 200*256 > varc && !s->intra_penalty)
977  mb_type|= CANDIDATE_MB_TYPE_INTRA;
978  if (varc*2 + 200*256 > vard || s->c.qscale > 24){
979 // if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){
980  mb_type|= CANDIDATE_MB_TYPE_INTER;
981  c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
982  if (s->mpv_flags & FF_MPV_FLAG_MV0)
983  if(mx || my)
984  mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference
985  }else{
986  mx *= 1 << shift;
987  my *= 1 << shift;
988  }
989  if ((c->avctx->flags & AV_CODEC_FLAG_4MV)
990  && !c->skip && varc>50<<8 && vard>10<<8){
991  if(h263_mv4_search(s, mx, my, shift) < INT_MAX)
992  mb_type|=CANDIDATE_MB_TYPE_INTER4V;
993 
994  set_p_mv_tables(s, mx, my, 0);
995  }else
996  set_p_mv_tables(s, mx, my, 1);
997  if ((c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)
998  && !c->skip){ //FIXME varc/d checks
999  if(interlaced_search(s, 0, s->c.p_field_mv_table, s->p_field_select_table, mx, my, 0) < INT_MAX)
1000  mb_type |= CANDIDATE_MB_TYPE_INTER_I;
1001  }
1002  }else{
1003  int intra_score, i;
1004  mb_type= CANDIDATE_MB_TYPE_INTER;
1005 
1006  dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1007  if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1008  dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
1009 
1010  if ((c->avctx->flags & AV_CODEC_FLAG_4MV)
1011  && !c->skip && varc>50<<8 && vard>10<<8){
1012  int dmin4= h263_mv4_search(s, mx, my, shift);
1013  if(dmin4 < dmin){
1014  mb_type= CANDIDATE_MB_TYPE_INTER4V;
1015  dmin=dmin4;
1016  }
1017  }
1018  if ((c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)
1019  && !c->skip){ //FIXME varc/d checks
1020  int dmin_i= interlaced_search(s, 0, s->c.p_field_mv_table, s->p_field_select_table, mx, my, 0);
1021  if(dmin_i < dmin){
1022  mb_type = CANDIDATE_MB_TYPE_INTER_I;
1023  dmin= dmin_i;
1024  }
1025  }
1026 
1028 
1029  /* get intra luma score */
1030  if((c->avctx->mb_cmp&0xFF)==FF_CMP_SSE){
1031  intra_score= varc - 500;
1032  }else{
1033  unsigned mean = (sum+128)>>8;
1034  mean*= 0x01010101;
1035 
1036  for(i=0; i<16; i++){
1037  *(uint32_t*)(&c->scratchpad[i*s->c.linesize+ 0]) = mean;
1038  *(uint32_t*)(&c->scratchpad[i*s->c.linesize+ 4]) = mean;
1039  *(uint32_t*)(&c->scratchpad[i*s->c.linesize+ 8]) = mean;
1040  *(uint32_t*)(&c->scratchpad[i*s->c.linesize+12]) = mean;
1041  }
1042 
1043  intra_score= c->mb_cmp[0](s, c->scratchpad, pix, s->c.linesize, 16);
1044  }
1045  intra_score += c->mb_penalty_factor*16 + s->intra_penalty;
1046 
1047  if(intra_score < dmin){
1048  mb_type= CANDIDATE_MB_TYPE_INTRA;
1049  s->c.cur_pic.mb_type[mb_y*s->c.mb_stride + mb_x] = CANDIDATE_MB_TYPE_INTRA; //FIXME cleanup
1050  }else
1051  s->c.cur_pic.mb_type[mb_y*s->c.mb_stride + mb_x] = 0;
1052 
1053  {
1054  int p_score = FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
1055  int i_score = varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
1056  c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
1057  }
1058  }
1059 
1060  s->mb_type[mb_y*s->c.mb_stride + mb_x] = mb_type;
1061 }
1062 
1064  int mb_x, int mb_y)
1065 {
1066  MotionEstContext *const c = &s->me;
1067  int mx, my, dmin;
1068  int P[10][2];
1069  const int shift = 1 + s->c.quarter_sample;
1070  const int xy = mb_x + mb_y*s->c.mb_stride;
1071  init_ref(c, s->new_pic->data, s->c.last_pic.data, NULL, 16*mb_x, 16*mb_y, 0);
1072 
1073  av_assert0(s->c.quarter_sample == 0 || s->c.quarter_sample == 1);
1074 
1075  c->pre_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_pre_cmp);
1076  c->current_mv_penalty = c->mv_penalty[s->f_code] + MAX_DMV;
1077 
1078  get_limits(s, 16*mb_x, 16*mb_y, 0);
1079  c->skip=0;
1080 
1081  P_LEFT[0] = FFMAX(s->p_mv_table[xy + 1][0], c->xmin * (1 << shift));
1082  P_LEFT[1] = s->p_mv_table[xy + 1][1];
1083 
1084  /* special case for first line */
1085  if (s->c.first_slice_line) {
1086  c->pred_x= P_LEFT[0];
1087  c->pred_y= P_LEFT[1];
1088  P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]=
1089  P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0; //FIXME
1090  } else {
1091  P_TOP[0] = s->p_mv_table[xy + s->c.mb_stride ][0];
1092  P_TOP[1] = s->p_mv_table[xy + s->c.mb_stride ][1];
1093  P_TOPRIGHT[0] = s->p_mv_table[xy + s->c.mb_stride - 1][0];
1094  P_TOPRIGHT[1] = s->p_mv_table[xy + s->c.mb_stride - 1][1];
1095  if(P_TOP[1] < (c->ymin<<shift)) P_TOP[1] = (c->ymin<<shift);
1096  if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
1097  if(P_TOPRIGHT[1] < (c->ymin<<shift)) P_TOPRIGHT[1]= (c->ymin<<shift);
1098 
1099  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1100  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1101 
1102  c->pred_x = P_MEDIAN[0];
1103  c->pred_y = P_MEDIAN[1];
1104  }
1105 
1106  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
1107 
1108  s->p_mv_table[xy][0] = mx<<shift;
1109  s->p_mv_table[xy][1] = my<<shift;
1110 
1111  return dmin;
1112 }
1113 
1114 static int estimate_motion_b(MPVEncContext *const s, int mb_x, int mb_y,
1115  int16_t (*mv_table)[2], int ref_index, int f_code)
1116 {
1117  MotionEstContext *const c = &s->me;
1118  int mx = 0, my = 0, dmin = 0;
1119  int P[10][2];
1120  const int shift= 1+s->c.quarter_sample;
1121  const int mot_stride = s->c.mb_stride;
1122  const int mot_xy = mb_y*mot_stride + mb_x;
1123  const uint8_t * const mv_penalty = c->mv_penalty[f_code] + MAX_DMV;
1124  int mv_scale;
1125 
1126  c->current_mv_penalty= mv_penalty;
1127 
1128  get_limits(s, 16*mb_x, 16*mb_y, 1);
1129 
1130  if (c->motion_est != FF_ME_ZERO) {
1131  P_LEFT[0] = mv_table[mot_xy - 1][0];
1132  P_LEFT[1] = mv_table[mot_xy - 1][1];
1133 
1134  if (P_LEFT[0] > (c->xmax << shift)) P_LEFT[0] = (c->xmax << shift);
1135 
1136  /* special case for first line */
1137  if (!s->c.first_slice_line) {
1138  P_TOP[0] = mv_table[mot_xy - mot_stride ][0];
1139  P_TOP[1] = mv_table[mot_xy - mot_stride ][1];
1140  P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1][0];
1141  P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1][1];
1142  if (P_TOP[1] > (c->ymax << shift)) P_TOP[1] = (c->ymax << shift);
1143  if (P_TOPRIGHT[0] < c->xmin * (1 << shift)) P_TOPRIGHT[0] = c->xmin * (1 << shift);
1144  if (P_TOPRIGHT[1] > (c->ymax << shift)) P_TOPRIGHT[1] = (c->ymax << shift);
1145 
1146  P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1147  P_MEDIAN[1] = mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1148  }
1149  c->pred_x = P_LEFT[0];
1150  c->pred_y = P_LEFT[1];
1151 
1152  if(mv_table == s->b_forw_mv_table){
1153  mv_scale= (s->c.pb_time<<16) / (s->c.pp_time<<shift);
1154  }else{
1155  mv_scale = ((s->c.pb_time - s->c.pp_time) * (1 << 16)) / (s->c.pp_time<<shift);
1156  }
1157 
1158  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->p_mv_table, mv_scale, 0, 16);
1159  }
1160 
1161  dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, ref_index, 0, 16);
1162 
1163  if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1164  dmin= get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1);
1165 
1166 // s->mb_type[mb_y*s->c.mb_width + mb_x]= mb_type;
1167  mv_table[mot_xy][0]= mx;
1168  mv_table[mot_xy][1]= my;
1169 
1170  return dmin;
1171 }
1172 
1173 static inline int check_bidir_mv(MPVEncContext *const s,
1174  int motion_fx, int motion_fy,
1175  int motion_bx, int motion_by,
1176  int pred_fx, int pred_fy,
1177  int pred_bx, int pred_by,
1178  int size, int h)
1179 {
1180  //FIXME optimize?
1181  //FIXME better f_code prediction (max mv & distance)
1182  //FIXME pointers
1183  MotionEstContext *const c = &s->me;
1184  const uint8_t * const mv_penalty_f = c->mv_penalty[s->f_code] + MAX_DMV; // f_code of the prev frame
1185  const uint8_t * const mv_penalty_b = c->mv_penalty[s->b_code] + MAX_DMV; // f_code of the prev frame
1186  int stride= c->stride;
1187  uint8_t *dest_y = c->scratchpad;
1188  const uint8_t *ptr;
1189  int dxy;
1190  int src_x, src_y;
1191  int fbmin;
1192  const uint8_t *const *src_data = c->src[0];
1193  const uint8_t *const *ref_data = c->ref[0];
1194  const uint8_t *const *ref2_data = c->ref[2];
1195 
1196  if(s->c.quarter_sample){
1197  dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
1198  src_x = motion_fx >> 2;
1199  src_y = motion_fy >> 2;
1200 
1201  ptr = ref_data[0] + (src_y * stride) + src_x;
1202  s->c.qdsp.put_qpel_pixels_tab[0][dxy](dest_y, ptr, stride);
1203 
1204  dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
1205  src_x = motion_bx >> 2;
1206  src_y = motion_by >> 2;
1207 
1208  ptr = ref2_data[0] + (src_y * stride) + src_x;
1209  s->c.qdsp.avg_qpel_pixels_tab[size][dxy](dest_y, ptr, stride);
1210  }else{
1211  dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1212  src_x = motion_fx >> 1;
1213  src_y = motion_fy >> 1;
1214 
1215  ptr = ref_data[0] + (src_y * stride) + src_x;
1216  s->c.hdsp.put_pixels_tab[size][dxy](dest_y , ptr , stride, h);
1217 
1218  dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
1219  src_x = motion_bx >> 1;
1220  src_y = motion_by >> 1;
1221 
1222  ptr = ref2_data[0] + (src_y * stride) + src_x;
1223  s->c.hdsp.avg_pixels_tab[size][dxy](dest_y , ptr , stride, h);
1224  }
1225 
1226  fbmin = (mv_penalty_f[motion_fx-pred_fx] + mv_penalty_f[motion_fy-pred_fy])*c->mb_penalty_factor
1227  +(mv_penalty_b[motion_bx-pred_bx] + mv_penalty_b[motion_by-pred_by])*c->mb_penalty_factor
1228  + c->mb_cmp[size](s, src_data[0], dest_y, stride, h); // FIXME new_pic
1229 
1230  if(c->avctx->mb_cmp&FF_CMP_CHROMA){
1231  }
1232  //FIXME CHROMA !!!
1233 
1234  return fbmin;
1235 }
1236 
1237 /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1238 static inline int bidir_refine(MPVEncContext *const s, int mb_x, int mb_y)
1239 {
1240  MotionEstContext *const c = &s->me;
1241  const int mot_stride = s->c.mb_stride;
1242  const int xy = mb_y *mot_stride + mb_x;
1243  int fbmin;
1244  int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
1245  int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
1246  int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
1247  int pred_by= s->b_bidir_back_mv_table[xy-1][1];
1248  int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
1249  int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
1250  int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
1251  int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
1252  const int flags= c->sub_flags;
1253  const int qpel= flags&FLAG_QPEL;
1254  const int shift= 1+qpel;
1255  const int xmin= c->xmin * (1 << shift);
1256  const int ymin= c->ymin * (1 << shift);
1257  const int xmax= c->xmax<<shift;
1258  const int ymax= c->ymax<<shift;
1259 #define HASH(fx,fy,bx,by) ((fx)+17*(fy)+63*(bx)+117*(by))
1260 #define HASH8(fx,fy,bx,by) ((uint8_t)HASH(fx,fy,bx,by))
1261  int hashidx= HASH(motion_fx,motion_fy, motion_bx, motion_by);
1262  uint8_t map[256] = { 0 };
1263 
1264  map[hashidx&255] = 1;
1265 
1266  fbmin= check_bidir_mv(s, motion_fx, motion_fy,
1267  motion_bx, motion_by,
1268  pred_fx, pred_fy,
1269  pred_bx, pred_by,
1270  0, 16);
1271 
1272  if (c->avctx->bidir_refine) {
1273  int end;
1274  static const uint8_t limittab[5]={0,8,32,64,80};
1275  const int limit = limittab[c->avctx->bidir_refine];
1276  static const int8_t vect[][4]={
1277 { 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},
1278 
1279 { 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},
1280 { 0, 1, 0, 1}, { 0,-1, 0,-1}, { 1, 0, 1, 0}, {-1, 0,-1, 0},
1281 { 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},
1282 { 0,-1, 0, 1}, { 0, 1, 0,-1}, {-1, 0, 1, 0}, { 1, 0,-1, 0},
1283 
1284 { 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},
1285 { 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},
1286 { 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},
1287 { 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},
1288 
1289 { 1, 1, 1, 1}, {-1,-1,-1,-1},
1290 { 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},
1291 { 1, 1,-1,-1}, {-1,-1, 1, 1}, { 1,-1,-1, 1}, {-1, 1, 1,-1}, { 1,-1, 1,-1}, {-1, 1,-1, 1},
1292  };
1293  static const uint8_t hash[]={
1294 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),
1295 
1296 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),
1297 HASH8( 0, 1, 0, 1), HASH8( 0,-1, 0,-1), HASH8( 1, 0, 1, 0), HASH8(-1, 0,-1, 0),
1298 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),
1299 HASH8( 0,-1, 0, 1), HASH8( 0, 1, 0,-1), HASH8(-1, 0, 1, 0), HASH8( 1, 0,-1, 0),
1300 
1301 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),
1302 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),
1303 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),
1304 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),
1305 
1306 HASH8( 1, 1, 1, 1), HASH8(-1,-1,-1,-1),
1307 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),
1308 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),
1309 };
1310 
1311 #define CHECK_BIDIR(fx,fy,bx,by)\
1312  if( !map[(hashidx+HASH(fx,fy,bx,by))&255]\
1313  &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\
1314  &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\
1315  int score;\
1316  map[(hashidx+HASH(fx,fy,bx,by))&255] = 1;\
1317  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);\
1318  if(score < fbmin){\
1319  hashidx += HASH(fx,fy,bx,by);\
1320  fbmin= score;\
1321  motion_fx+=fx;\
1322  motion_fy+=fy;\
1323  motion_bx+=bx;\
1324  motion_by+=by;\
1325  end=0;\
1326  }\
1327  }
1328 #define CHECK_BIDIR2(a,b,c,d)\
1329 CHECK_BIDIR(a,b,c,d)\
1330 CHECK_BIDIR(-(a),-(b),-(c),-(d))
1331 
1332  do{
1333  int i;
1334  int borderdist=0;
1335  end=1;
1336 
1337  CHECK_BIDIR2(0,0,0,1)
1338  CHECK_BIDIR2(0,0,1,0)
1339  CHECK_BIDIR2(0,1,0,0)
1340  CHECK_BIDIR2(1,0,0,0)
1341 
1342  for(i=8; i<limit; i++){
1343  int fx= motion_fx+vect[i][0];
1344  int fy= motion_fy+vect[i][1];
1345  int bx= motion_bx+vect[i][2];
1346  int by= motion_by+vect[i][3];
1347  if(borderdist<=0){
1348  int a= (xmax - FFMAX(fx,bx))|(FFMIN(fx,bx) - xmin);
1349  int b= (ymax - FFMAX(fy,by))|(FFMIN(fy,by) - ymin);
1350  if((a|b) < 0)
1351  map[(hashidx+hash[i])&255] = 1;
1352  }
1353  if(!map[(hashidx+hash[i])&255]){
1354  int score;
1355  map[(hashidx+hash[i])&255] = 1;
1356  score= check_bidir_mv(s, fx, fy, bx, by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);
1357  if(score < fbmin){
1358  hashidx += hash[i];
1359  fbmin= score;
1360  motion_fx=fx;
1361  motion_fy=fy;
1362  motion_bx=bx;
1363  motion_by=by;
1364  end=0;
1365  borderdist--;
1366  if(borderdist<=0){
1367  int a= FFMIN(xmax - FFMAX(fx,bx), FFMIN(fx,bx) - xmin);
1368  int b= FFMIN(ymax - FFMAX(fy,by), FFMIN(fy,by) - ymin);
1369  borderdist= FFMIN(a,b);
1370  }
1371  }
1372  }
1373  }
1374  }while(!end);
1375  }
1376 
1377  s->b_bidir_forw_mv_table[xy][0]= motion_fx;
1378  s->b_bidir_forw_mv_table[xy][1]= motion_fy;
1379  s->b_bidir_back_mv_table[xy][0]= motion_bx;
1380  s->b_bidir_back_mv_table[xy][1]= motion_by;
1381 
1382  return fbmin;
1383 }
1384 
1385 static inline int direct_search(MPVEncContext *const s, int mb_x, int mb_y)
1386 {
1387  MotionEstContext *const c = &s->me;
1388  int P[10][2];
1389  const int mot_stride = s->c.mb_stride;
1390  const int mot_xy = mb_y*mot_stride + mb_x;
1391  const int shift= 1+s->c.quarter_sample;
1392  int dmin, i;
1393  const int time_pp= s->c.pp_time;
1394  const int time_pb= s->c.pb_time;
1395  int mx, my, xmin, xmax, ymin, ymax;
1396  int16_t (*mv_table)[2]= s->b_direct_mv_table;
1397 
1398  c->current_mv_penalty= c->mv_penalty[1] + MAX_DMV;
1399  ymin= xmin=(-32)>>shift;
1400  ymax= xmax= 31>>shift;
1401 
1402  if (IS_8X8(s->c.next_pic.mb_type[mot_xy])) {
1403  s->c.mv_type = MV_TYPE_8X8;
1404  }else{
1405  s->c.mv_type = MV_TYPE_16X16;
1406  }
1407 
1408  for(i=0; i<4; i++){
1409  int index= s->c.block_index[i];
1410  int min, max;
1411 
1412  c->co_located_mv[i][0] = s->c.next_pic.motion_val[0][index][0];
1413  c->co_located_mv[i][1] = s->c.next_pic.motion_val[0][index][1];
1414  c->direct_basis_mv[i][0]= c->co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3));
1415  c->direct_basis_mv[i][1]= c->co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));
1416 // c->direct_basis_mv[1][i][0]= c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
1417 // c->direct_basis_mv[1][i][1]= c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);
1418 
1419  max= FFMAX(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
1420  min= FFMIN(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
1421  max+= 16*mb_x + 1; // +-1 is for the simpler rounding
1422  min+= 16*mb_x - 1;
1423  xmax= FFMIN(xmax, s->c.width - max);
1424  xmin= FFMAX(xmin, - 16 - min);
1425 
1426  max= FFMAX(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
1427  min= FFMIN(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
1428  max+= 16*mb_y + 1; // +-1 is for the simpler rounding
1429  min+= 16*mb_y - 1;
1430  ymax= FFMIN(ymax, s->c.height - max);
1431  ymin= FFMAX(ymin, - 16 - min);
1432 
1433  if(s->c.mv_type == MV_TYPE_16X16) break;
1434  }
1435 
1436  av_assert2(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16);
1437 
1438  if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){
1439  s->b_direct_mv_table[mot_xy][0]= 0;
1440  s->b_direct_mv_table[mot_xy][1]= 0;
1441 
1442  return 256*256*256*64-1;
1443  }
1444 
1445  c->xmin= xmin;
1446  c->ymin= ymin;
1447  c->xmax= xmax;
1448  c->ymax= ymax;
1449  c->flags |= FLAG_DIRECT;
1450  c->sub_flags |= FLAG_DIRECT;
1451  c->pred_x=0;
1452  c->pred_y=0;
1453 
1454  P_LEFT[0] = av_clip(mv_table[mot_xy - 1][0], xmin * (1 << shift), xmax << shift);
1455  P_LEFT[1] = av_clip(mv_table[mot_xy - 1][1], ymin * (1 << shift), ymax << shift);
1456 
1457  /* special case for first line */
1458  if (!s->c.first_slice_line) { //FIXME maybe allow this over thread boundary as it is clipped
1459  P_TOP[0] = av_clip(mv_table[mot_xy - mot_stride ][0], xmin * (1 << shift), xmax << shift);
1460  P_TOP[1] = av_clip(mv_table[mot_xy - mot_stride ][1], ymin * (1 << shift), ymax << shift);
1461  P_TOPRIGHT[0] = av_clip(mv_table[mot_xy - mot_stride + 1][0], xmin * (1 << shift), xmax << shift);
1462  P_TOPRIGHT[1] = av_clip(mv_table[mot_xy - mot_stride + 1][1], ymin * (1 << shift), ymax << shift);
1463 
1464  P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1465  P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1466  }
1467 
1468  dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, mv_table, 1<<(16-shift), 0, 16);
1469  if(c->sub_flags&FLAG_QPEL)
1470  dmin = qpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1471  else
1472  dmin = hpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1473 
1474  if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1475  dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
1476 
1477  get_limits(s, 16*mb_x, 16*mb_y, 1); //restore c->?min/max, maybe not needed
1478 
1479  mv_table[mot_xy][0]= mx;
1480  mv_table[mot_xy][1]= my;
1481  c->flags &= ~FLAG_DIRECT;
1482  c->sub_flags &= ~FLAG_DIRECT;
1483 
1484  return dmin;
1485 }
1486 
1488  int mb_x, int mb_y)
1489 {
1490  MotionEstContext *const c = &s->me;
1491  int fmin, bmin, dmin, fbmin, bimin, fimin;
1492  int type=0;
1493  const int xy = mb_y*s->c.mb_stride + mb_x;
1494  init_ref(c, s->new_pic->data, s->c.last_pic.data,
1495  s->c.next_pic.data, 16 * mb_x, 16 * mb_y, 2);
1496 
1497  get_limits(s, 16*mb_x, 16*mb_y, 1);
1498 
1499  c->skip=0;
1500 
1501  if (s->c.codec_id == AV_CODEC_ID_MPEG4 && s->c.next_pic.mbskip_table[xy]) {
1502  int score= direct_search(s, mb_x, mb_y); //FIXME just check 0,0
1503 
1504  score= ((unsigned)(score*score + 128*256))>>16;
1505  c->mc_mb_var_sum_temp += score;
1506  s->mc_mb_var[mb_y*s->c.mb_stride + mb_x] = score; //FIXME use SSE
1507  s->mb_type[mb_y*s->c.mb_stride + mb_x]= CANDIDATE_MB_TYPE_DIRECT0;
1508 
1509  return;
1510  }
1511 
1512  c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
1513  c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
1514  c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
1515 
1516  if (s->c.codec_id == AV_CODEC_ID_MPEG4)
1517  dmin= direct_search(s, mb_x, mb_y);
1518  else
1519  dmin= INT_MAX;
1520 
1521 // FIXME penalty stuff for non-MPEG-4
1522  c->skip=0;
1523  fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) +
1524  3 * c->mb_penalty_factor;
1525 
1526  c->skip=0;
1527  bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) +
1528  2 * c->mb_penalty_factor;
1529  ff_dlog(c->avctx, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1530 
1531  c->skip=0;
1532  fbmin= bidir_refine(s, mb_x, mb_y) + c->mb_penalty_factor;
1533  ff_dlog(c->avctx, "%d %d %d %d\n", dmin, fmin, bmin, fbmin);
1534 
1535  if (c->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
1536 //FIXME mb type penalty
1537  c->skip=0;
1538  c->current_mv_penalty = c->mv_penalty[s->f_code] + MAX_DMV;
1539  fimin= interlaced_search(s, 0,
1540  s->b_field_mv_table[0], s->b_field_select_table[0],
1541  s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0);
1542  c->current_mv_penalty = c->mv_penalty[s->b_code] + MAX_DMV;
1543  bimin= interlaced_search(s, 2,
1544  s->b_field_mv_table[1], s->b_field_select_table[1],
1545  s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0);
1546  }else
1547  fimin= bimin= INT_MAX;
1548 
1549  {
1550  int score= fmin;
1552 
1553  if (dmin <= score){
1554  score = dmin;
1556  }
1557  if(bmin<score){
1558  score=bmin;
1560  }
1561  if(fbmin<score){
1562  score=fbmin;
1564  }
1565  if(fimin<score){
1566  score=fimin;
1568  }
1569  if(bimin<score){
1570  score=bimin;
1572  }
1573 
1574  score= ((unsigned)(score*score + 128*256))>>16;
1575  c->mc_mb_var_sum_temp += score;
1576  s->mc_mb_var[mb_y*s->c.mb_stride + mb_x] = score; //FIXME use SSE
1577  }
1578 
1579  if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
1581  if(fimin < INT_MAX)
1583  if(bimin < INT_MAX)
1585  if(fimin < INT_MAX && bimin < INT_MAX){
1587  }
1588  //FIXME something smarter
1589  if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //do not try direct mode if it is invalid for this MB
1590  if (s->c.codec_id == AV_CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT &&
1591  s->mpv_flags & FF_MPV_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy])
1593  }
1594 
1595  s->mb_type[mb_y*s->c.mb_stride + mb_x]= type;
1596 }
1597 
1598 /* find best f_code for ME which do unlimited searches */
1599 int ff_get_best_fcode(MPVMainEncContext *const m, const int16_t (*mv_table)[2], int type)
1600 {
1601  MPVEncContext *const s = &m->s;
1602  MotionEstContext *const c = &s->me;
1603 
1604  if (c->motion_est != FF_ME_ZERO) {
1605  int score[8];
1606  int i, range = c->avctx->me_range ? c->avctx->me_range : (INT_MAX/2);
1607  const uint8_t * fcode_tab = m->fcode_tab;
1608  int best_fcode=-1;
1609  int best_score=-10000000;
1610 
1611  if (s->c.msmpeg4_version != MSMP4_UNUSED)
1612  range= FFMIN(range, 16);
1613  else if (s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO &&
1614  c->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)
1615  range= FFMIN(range, 256);
1616 
1617  for(i=0; i<8; i++) score[i]= s->c.mb_num*(8-i);
1618 
1619  for (int y = 0; y < s->c.mb_height; y++) {
1620  int x;
1621  int xy= y*s->c.mb_stride;
1622  for(x=0; x<s->c.mb_width; x++, xy++){
1623  if(s->mb_type[xy] & type){
1624  int mx= mv_table[xy][0];
1625  int my= mv_table[xy][1];
1626  int fcode = FFMAX(fcode_tab[mx], fcode_tab[my]);
1627  int j;
1628 
1629  if (mx >= range || mx < -range ||
1630  my >= range || my < -range)
1631  continue;
1632 
1633  for(j=0; j<fcode && j<8; j++){
1634  if (s->c.pict_type == AV_PICTURE_TYPE_B ||
1635  s->mc_mb_var[xy] < s->mb_var[xy])
1636  score[j]-= 170;
1637  }
1638  }
1639  }
1640  }
1641 
1642  for(i=1; i<8; i++){
1643  if(score[i] > best_score){
1644  best_score= score[i];
1645  best_fcode= i;
1646  }
1647  }
1648 
1649  return best_fcode;
1650  }else{
1651  return 1;
1652  }
1653 }
1654 
1656 {
1657  MotionEstContext *const c = &s->me;
1658  const int f_code= s->f_code;
1659  int y, range;
1660  av_assert0(s->c.pict_type == AV_PICTURE_TYPE_P);
1661 
1662  range = (((s->c.out_format == FMT_MPEG1 || s->c.msmpeg4_version != MSMP4_UNUSED) ? 8 : 16) << f_code);
1663 
1664  av_assert0(range <= 16 || s->c.msmpeg4_version == MSMP4_UNUSED);
1665  av_assert0(range <=256 || !(s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO && c->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL));
1666 
1667  if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
1668 
1669  if (c->avctx->flags & AV_CODEC_FLAG_4MV) {
1670  const int wrap= s->c.b8_stride;
1671 
1672  /* clip / convert to intra 8x8 type MVs */
1673  for(y=0; y<s->c.mb_height; y++){
1674  int xy= y*2*wrap;
1675  int i= y*s->c.mb_stride;
1676  int x;
1677 
1678  for(x=0; x<s->c.mb_width; x++){
1679  if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){
1680  int block;
1681  for(block=0; block<4; block++){
1682  int off= (block& 1) + (block>>1)*wrap;
1683  int mx = s->c.cur_pic.motion_val[0][ xy + off ][0];
1684  int my = s->c.cur_pic.motion_val[0][ xy + off ][1];
1685 
1686  if( mx >=range || mx <-range
1687  || my >=range || my <-range){
1688  s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
1689  s->mb_type[i] |= type;
1690  s->c.cur_pic.mb_type[i] = type;
1691  }
1692  }
1693  }
1694  xy+=2;
1695  i++;
1696  }
1697  }
1698  }
1699 }
1700 
1701 /**
1702  * @param truncate 1 for truncation, 0 for using intra
1703  */
1704 void ff_fix_long_mvs(MPVEncContext *const s, uint8_t *field_select_table, int field_select,
1705  int16_t (*mv_table)[2], int f_code, int type, int truncate)
1706 {
1707  MotionEstContext *const c = &s->me;
1708  int y, h_range, v_range;
1709 
1710  // RAL: 8 in MPEG-1, 16 in MPEG-4
1711  int range = (((s->c.out_format == FMT_MPEG1 || s->c.msmpeg4_version != MSMP4_UNUSED) ? 8 : 16) << f_code);
1712 
1713  if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
1714 
1715  h_range= range;
1716  v_range= field_select_table ? range>>1 : range;
1717 
1718  /* clip / convert to intra 16x16 type MVs */
1719  for(y=0; y<s->c.mb_height; y++){
1720  int x;
1721  int xy= y*s->c.mb_stride;
1722  for(x=0; x<s->c.mb_width; x++){
1723  if (s->mb_type[xy] & type){ // RAL: "type" test added...
1724  if (!field_select_table || field_select_table[xy] == field_select) {
1725  if( mv_table[xy][0] >=h_range || mv_table[xy][0] <-h_range
1726  || mv_table[xy][1] >=v_range || mv_table[xy][1] <-v_range){
1727 
1728  if(truncate){
1729  if (mv_table[xy][0] > h_range-1) mv_table[xy][0]= h_range-1;
1730  else if(mv_table[xy][0] < -h_range ) mv_table[xy][0]= -h_range;
1731  if (mv_table[xy][1] > v_range-1) mv_table[xy][1]= v_range-1;
1732  else if(mv_table[xy][1] < -v_range ) mv_table[xy][1]= -v_range;
1733  }else{
1734  s->mb_type[xy] &= ~type;
1735  s->mb_type[xy] |= CANDIDATE_MB_TYPE_INTRA;
1736  mv_table[xy][0]=
1737  mv_table[xy][1]= 0;
1738  }
1739  }
1740  }
1741  }
1742  xy++;
1743  }
1744  }
1745 }
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:62
ff_fix_long_p_mvs
void ff_fix_long_p_mvs(MPVEncContext *const s, int type)
Definition: motion_est.c:1655
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:1704
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:1487
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:1114
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
static 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:1173
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:745
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:1238
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:42
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:863
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:1063
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:731
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
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
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:1385
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
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:58
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:888
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:1599