dct-domain noise reduction (ported from lavc)
[x262.git] / encoder / me.c
1 /*****************************************************************************
2  * me.c: h264 encoder library (Motion Estimation)
3  *****************************************************************************
4  * Copyright (C) 2003 Laurent Aimar
5  * $Id: me.c,v 1.1 2004/06/03 19:27:08 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Loren Merritt <lorenm@u.washington.edu>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program 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
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "common/common.h"
30 #include "me.h"
31
32 /* presets selected from good points on the speed-vs-quality curve of several test videos
33  * subpel_iters[i_subpel_refine] = { refine_hpel, refine_qpel, me_hpel, me_qpel }
34  * where me_* are the number of EPZS iterations run on all candidate block types,
35  * and refine_* are run only on the winner. */
36 static const int subpel_iterations[][4] = 
37    {{1,0,0,0},
38     {1,1,0,0},
39     {0,1,1,0},
40     {0,2,1,0},
41     {0,2,1,1},
42     {0,2,1,2},
43     {0,0,2,2}};
44
45 static void refine_subpel( x264_t *h, x264_me_t *m, int hpel_iters, int qpel_iters, int *p_halfpel_thresh, int b_refine_qpel );
46
47 #define COST_MV_INT( mx, my, bd, d ) \
48 { \
49     int cost = h->pixf.sad[i_pixel]( m->p_fenc[0], m->i_stride[0],     \
50                    &p_fref[(my)*m->i_stride[0]+(mx)], m->i_stride[0] ) \
51              + p_cost_mvx[ (mx)<<2 ]  \
52              + p_cost_mvy[ (my)<<2 ]; \
53     if( cost < bcost ) \
54     {                  \
55         bcost = cost;  \
56         bmx = mx;      \
57         bmy = my;      \
58         if( bd ) \
59             dir = d; \
60     } \
61 }
62 #define COST_MV( mx, my )         COST_MV_INT( mx, my, 0, 0 )
63 #define COST_MV_DIR( mx, my, d )  COST_MV_INT( mx, my, 1, d )
64
65 #define COST_MV_PDE( mx, my ) \
66 { \
67     int cost = h->pixf.sad_pde[i_pixel]( m->p_fenc[0], m->i_stride[0], \
68                    &p_fref[(my)*m->i_stride[0]+(mx)], m->i_stride[0], \
69                    bcost - p_cost_mvx[ (mx)<<2 ] - p_cost_mvy[ (my)<<2 ] ); \
70     if( cost < bcost - p_cost_mvx[ (mx)<<2 ] - p_cost_mvy[ (my)<<2 ] ) \
71     {                  \
72         bcost = cost + p_cost_mvx[ (mx)<<2 ] + p_cost_mvy[ (my)<<2 ];  \
73         bmx = mx;      \
74         bmy = my;      \
75     } \
76 }
77
78 #define DIA1_ITER( mx, my )\
79     {\
80         omx = mx; omy = my;\
81         COST_MV( omx  , omy-1 );/*  1  */\
82         COST_MV( omx  , omy+1 );/* 101 */\
83         COST_MV( omx-1, omy   );/*  1  */\
84         COST_MV( omx+1, omy   );\
85     }
86
87
88 void x264_me_search_ref( x264_t *h, x264_me_t *m, int (*mvc)[2], int i_mvc, int *p_halfpel_thresh )
89 {
90     const int i_pixel = m->i_pixel;
91     const int i_me_range = h->param.analyse.i_me_range;
92     int bmx, bmy, bcost;
93     int omx, omy, pmx, pmy;
94     uint8_t *p_fref = m->p_fref[0];
95     int i, j;
96     int dir;
97
98     int mv_x_min = h->mb.mv_min_fpel[0];
99     int mv_y_min = h->mb.mv_min_fpel[1];
100     int mv_x_max = h->mb.mv_max_fpel[0];
101     int mv_y_max = h->mb.mv_max_fpel[1];
102
103     const int16_t *p_cost_mvx = m->p_cost_mv - m->mvp[0];
104     const int16_t *p_cost_mvy = m->p_cost_mv - m->mvp[1];
105
106     if( h->mb.i_me_method == X264_ME_UMH )
107     {
108         /* clamp mvp to inside frame+padding, so that we don't have to check it each iteration */
109         p_cost_mvx = m->p_cost_mv - x264_clip3( m->mvp[0], h->mb.mv_min[0], h->mb.mv_max[0] );
110         p_cost_mvy = m->p_cost_mv - x264_clip3( m->mvp[1], h->mb.mv_min[1], h->mb.mv_max[1] );
111     }
112
113     bmx = pmx = x264_clip3( ( m->mvp[0] + 2 ) >> 2, mv_x_min, mv_x_max );
114     bmy = pmy = x264_clip3( ( m->mvp[1] + 2 ) >> 2, mv_y_min, mv_y_max );
115     bcost = COST_MAX;
116     COST_MV( pmx, pmy );
117     /* I don't know why this helps */
118     bcost -= p_cost_mvx[ bmx<<2 ] + p_cost_mvy[ bmy<<2 ];
119
120     /* try extra predictors if provided */
121     for( i = 0; i < i_mvc; i++ )
122     {
123         const int mx = x264_clip3( ( mvc[i][0] + 2 ) >> 2, mv_x_min, mv_x_max );
124         const int my = x264_clip3( ( mvc[i][1] + 2 ) >> 2, mv_y_min, mv_y_max );
125         if( mx != bmx || my != bmy )
126             COST_MV( mx, my );
127     }
128     
129     COST_MV( 0, 0 );
130
131     mv_x_max += 8;
132     mv_y_max += 8;
133     mv_x_min -= 8;
134     mv_y_min -= 8;
135
136     switch( h->mb.i_me_method )
137     {
138     case X264_ME_DIA:
139         /* diamond search, radius 1 */
140         for( i = 0; i < i_me_range; i++ )
141         {
142             DIA1_ITER( bmx, bmy );
143             if( bmx == omx && bmy == omy )
144                 break;
145         }
146         break;
147
148     case X264_ME_HEX:
149 me_hex2:
150         /* hexagon search, radius 2 */
151 #if 0
152         for( i = 0; i < i_me_range/2; i++ )
153         {
154             omx = bmx; omy = bmy;
155             COST_MV( omx-2, omy   );
156             COST_MV( omx-1, omy+2 );
157             COST_MV( omx+1, omy+2 );
158             COST_MV( omx+2, omy   );
159             COST_MV( omx+1, omy-2 );
160             COST_MV( omx-1, omy-2 );
161             if( bmx == omx && bmy == omy )
162                 break;
163         }
164 #else
165         /* equivalent to the above, but eliminates duplicate candidates */
166         dir = -1;
167         omx = bmx; omy = bmy;
168         COST_MV_DIR( omx-2, omy,   0 );
169         COST_MV_DIR( omx-1, omy+2, 1 );
170         COST_MV_DIR( omx+1, omy+2, 2 );
171         COST_MV_DIR( omx+2, omy,   3 );
172         COST_MV_DIR( omx+1, omy-2, 4 );
173         COST_MV_DIR( omx-1, omy-2, 5 );
174         if( dir != -1 )
175         {
176             for( i = 1; i < i_me_range/2; i++ )
177             {
178                 static const int hex2[8][2] = {{-1,-2}, {-2,0}, {-1,2}, {1,2}, {2,0}, {1,-2}, {-1,-2}, {-2,0}};
179                 static const int mod6[8] = {5,0,1,2,3,4,5,0};
180                 const int odir = mod6[dir+1];
181                 omx = bmx; omy = bmy;
182                 COST_MV_DIR( omx + hex2[odir+0][0], omy + hex2[odir+0][1], odir-1 );
183                 COST_MV_DIR( omx + hex2[odir+1][0], omy + hex2[odir+1][1], odir   );
184                 COST_MV_DIR( omx + hex2[odir+2][0], omy + hex2[odir+2][1], odir+1 );
185                 if( bmx == omx && bmy == omy )
186                     break;
187             }
188         }
189 #endif
190         /* square refine */
191         DIA1_ITER( bmx, bmy );
192         COST_MV( omx-1, omy-1 );
193         COST_MV( omx-1, omy+1 );
194         COST_MV( omx+1, omy-1 );
195         COST_MV( omx+1, omy+1 );
196         break;
197
198     case X264_ME_UMH:
199         {
200             /* Uneven-cross Multi-Hexagon-grid Search
201              * as in JM, except without early termination */
202
203             int ucost;
204             int cross_start;
205
206             /* refine predictors */
207             DIA1_ITER( pmx, pmy );
208             if( pmx || pmy )
209                 DIA1_ITER( 0, 0 );
210
211             if(i_pixel == PIXEL_4x4)
212                 goto me_hex2;
213
214             ucost = bcost;
215             if( (bmx || bmy) && (bmx!=pmx || bmy!=pmy) )
216                 DIA1_ITER( bmx, bmy );
217
218             /* cross */
219             omx = bmx; omy = bmy;
220             cross_start = ( bcost == ucost ) ? 3 : 1;
221             for( i = cross_start; i < i_me_range; i+=2 )
222             {
223                 if( omx + i <= mv_x_max )
224                     COST_MV( omx + i, omy );
225                 if( omx - i >= mv_x_min )
226                     COST_MV( omx - i, omy );
227             }
228             for( i = cross_start; i < i_me_range/2; i+=2 )
229             {
230                 if( omy + i <= mv_y_max )
231                     COST_MV( omx, omy + i );
232                 if( omy - i >= mv_y_min )
233                     COST_MV( omx, omy - i );
234             }
235
236             /* 5x5 ESA */
237             omx = bmx; omy = bmy;
238             for( i = (bcost == ucost) ? 4 : 0; i < 24; i++ )
239             {
240                 static const int square2[24][2] = {
241                     { 1, 0}, { 0, 1}, {-1, 0}, { 0,-1},
242                     { 1, 1}, {-1, 1}, {-1,-1}, { 1,-1},
243                     { 2,-1}, { 2, 0}, { 2, 1}, { 2, 2},
244                     { 1, 2}, { 0, 2}, {-1, 2}, {-2, 2},
245                     {-2, 1}, {-2, 0}, {-2,-1}, {-2,-2},
246                     {-1,-2}, { 0,-2}, { 1,-2}, { 2,-2}
247                 };
248                 COST_MV( omx + square2[i][0], omy + square2[i][1] );
249             }
250
251             /* hexagon grid */
252             omx = bmx; omy = bmy;
253             for( i = 1; i <= i_me_range/4; i++ )
254             {
255                 static const int hex4[16][2] = {
256                     {-4, 2}, {-4, 1}, {-4, 0}, {-4,-1}, {-4,-2},
257                     { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
258                     { 2, 3}, { 0, 4}, {-2, 3},
259                     {-2,-3}, { 0,-4}, { 2,-3},
260                 };
261                 const int bounds_check = 4*i > X264_MIN4( mv_x_max-omx, mv_y_max-omy, omx-mv_x_min, omy-mv_y_min );
262
263                 if( h->pixf.sad_pde[i_pixel] )
264                 {
265                     for( j = 0; j < 16; j++ )
266                     {
267                         int mx = omx + hex4[j][0]*i;
268                         int my = omy + hex4[j][1]*i;
269                         if( !bounds_check || ( mx >= mv_x_min && mx <= mv_x_max
270                                             && my >= mv_y_min && my <= mv_y_max ) )
271                             COST_MV_PDE( mx, my );
272                     }
273                 }
274                 else
275                 {
276                     for( j = 0; j < 16; j++ )
277                     {
278                         int mx = omx + hex4[j][0]*i;
279                         int my = omy + hex4[j][1]*i;
280                         if( !bounds_check || ( mx >= mv_x_min && mx <= mv_x_max
281                                             && my >= mv_y_min && my <= mv_y_max ) )
282                             COST_MV( mx, my );
283                     }
284                 }
285             }
286             goto me_hex2;
287         }
288
289     case X264_ME_ESA:
290         {
291             const int min_x = X264_MAX( bmx - i_me_range, mv_x_min);
292             const int min_y = X264_MAX( bmy - i_me_range, mv_y_min);
293             const int max_x = X264_MIN( bmx + i_me_range, mv_x_max);
294             const int max_y = X264_MIN( bmy + i_me_range, mv_y_max);
295             int mx, my;
296 #if 0
297             /* plain old exhaustive search */
298             for( my = min_y; my <= max_y; my++ )
299                 for( mx = min_x; mx <= max_x; mx++ )
300                     COST_MV( mx, my );
301 #else
302             /* successive elimination by comparing DC before a full SAD,
303              * because sum(abs(diff)) >= abs(diff(sum)). */
304             const int stride = m->i_stride[0];
305             const int dw = x264_pixel_size[i_pixel].w;
306             const int dh = x264_pixel_size[i_pixel].h * stride;
307             static uint8_t zero[16*16] = {0,};
308             const int enc_dc = h->pixf.sad[i_pixel]( m->p_fenc[0], stride, zero, 16 );
309             const uint16_t *integral_base = &m->integral[ -1 - 1*stride ];
310
311             if( h->pixf.sad_pde[i_pixel] )
312             {
313                 for( my = min_y; my <= max_y; my++ )
314                     for( mx = min_x; mx <= max_x; mx++ )
315                     {
316                         const uint16_t *integral = &integral_base[ mx + my * stride ];
317                         const uint16_t ref_dc = integral[  0 ] + integral[ dh + dw ]
318                                               - integral[ dw ] - integral[ dh ];
319                         const int bsad = bcost - p_cost_mvx[ (mx)<<2 ] - p_cost_mvy[ (my)<<2 ];
320                         if( abs( ref_dc - enc_dc ) < bsad )
321                             COST_MV_PDE( mx, my );
322                     }
323             }
324             else
325             {
326                 for( my = min_y; my <= max_y; my++ )
327                     for( mx = min_x; mx <= max_x; mx++ )
328                     {
329                         const uint16_t *integral = &integral_base[ mx + my * stride ];
330                         const uint16_t ref_dc = integral[  0 ] + integral[ dh + dw ]
331                                               - integral[ dw ] - integral[ dh ];
332                         const int bsad = bcost - p_cost_mvx[ (mx)<<2 ] - p_cost_mvy[ (my)<<2 ];
333                         if( abs( ref_dc - enc_dc ) < bsad )
334                             COST_MV( mx, my );
335                     }
336             }
337 #endif
338         }
339         break;
340     }
341
342     /* -> qpel mv */
343     m->mv[0] = bmx << 2;
344     m->mv[1] = bmy << 2;
345
346     /* compute the real cost */
347     m->cost_mv = p_cost_mvx[ m->mv[0] ] + p_cost_mvy[ m->mv[1] ];
348     m->cost = bcost;
349     if( bmx == pmx && bmy == pmy )
350         m->cost += m->cost_mv;
351     
352     /* subpel refine */
353     if( h->mb.i_subpel_refine >= 2 )
354     {
355         int hpel = subpel_iterations[h->mb.i_subpel_refine][2];
356         int qpel = subpel_iterations[h->mb.i_subpel_refine][3];
357         refine_subpel( h, m, hpel, qpel, p_halfpel_thresh, 0 );
358     }
359 }
360 #undef COST_MV
361
362 void x264_me_refine_qpel( x264_t *h, x264_me_t *m )
363 {
364     int hpel = subpel_iterations[h->mb.i_subpel_refine][0];
365     int qpel = subpel_iterations[h->mb.i_subpel_refine][1];
366
367     if( m->i_pixel <= PIXEL_8x8 && h->sh.i_type == SLICE_TYPE_P )
368         m->cost -= m->i_ref_cost;
369         
370     refine_subpel( h, m, hpel, qpel, NULL, 1 );
371 }
372
373 #define COST_MV_SAD( mx, my, dir ) \
374 if( b_refine_qpel || (dir^1) != odir ) \
375 { \
376     int stride = 16; \
377     uint8_t *src = h->mc.get_ref( m->p_fref, m->i_stride[0], pix, &stride, mx, my, bw, bh ); \
378     int cost = h->pixf.sad[i_pixel]( m->p_fenc[0], m->i_stride[0], src, stride ) \
379              + p_cost_mvx[ mx ] + p_cost_mvy[ my ]; \
380     if( cost < bcost ) \
381     {                  \
382         bcost = cost;  \
383         bmx = mx;      \
384         bmy = my;      \
385         bdir = dir;    \
386     } \
387 }
388
389 #define COST_MV_SATD( mx, my, dir ) \
390 if( b_refine_qpel || (dir^1) != odir ) \
391 { \
392     int stride = 16; \
393     uint8_t *src = h->mc.get_ref( m->p_fref, m->i_stride[0], pix, &stride, mx, my, bw, bh ); \
394     int cost = h->pixf.mbcmp[i_pixel]( m->p_fenc[0], m->i_stride[0], src, stride ) \
395              + p_cost_mvx[ mx ] + p_cost_mvy[ my ]; \
396     if( b_chroma_me && cost < bcost ) \
397     { \
398         h->mc.mc_chroma( m->p_fref[4], m->i_stride[1], pix, 8, mx, my, bw/2, bh/2 ); \
399         cost += h->pixf.mbcmp[i_pixel+3]( m->p_fenc[1], m->i_stride[1], pix, 8 ); \
400         if( cost < bcost ) \
401         { \
402             h->mc.mc_chroma( m->p_fref[5], m->i_stride[1], pix, 8, mx, my, bw/2, bh/2 ); \
403             cost += h->pixf.mbcmp[i_pixel+3]( m->p_fenc[2], m->i_stride[1], pix, 8 ); \
404         } \
405     } \
406     if( cost < bcost ) \
407     {                  \
408         bcost = cost;  \
409         bmx = mx;      \
410         bmy = my;      \
411         bdir = dir;    \
412     } \
413 }
414
415 static void refine_subpel( x264_t *h, x264_me_t *m, int hpel_iters, int qpel_iters, int *p_halfpel_thresh, int b_refine_qpel )
416 {
417     const int bw = x264_pixel_size[m->i_pixel].w;
418     const int bh = x264_pixel_size[m->i_pixel].h;
419     const int16_t *p_cost_mvx = m->p_cost_mv - m->mvp[0];
420     const int16_t *p_cost_mvy = m->p_cost_mv - m->mvp[1];
421     const int i_pixel = m->i_pixel;
422     const int b_chroma_me = h->mb.b_chroma_me && i_pixel <= PIXEL_8x8;
423
424     DECLARE_ALIGNED( uint8_t, pix[16*16], 16 );
425     int omx, omy;
426     int i;
427
428     int bmx = m->mv[0];
429     int bmy = m->mv[1];
430     int bcost = m->cost;
431     int odir = -1, bdir;
432
433
434     /* try the subpel component of the predicted mv */
435     if( hpel_iters )
436     {
437         int mx = x264_clip3( m->mvp[0], h->mb.mv_min[0], h->mb.mv_max[0] );
438         int my = x264_clip3( m->mvp[1], h->mb.mv_min[1], h->mb.mv_max[1] );
439         if( mx != bmx || my != bmy )
440             COST_MV_SAD( mx, my, -1 );
441     }
442     
443     /* hpel search */
444     bdir = -1;
445     for( i = hpel_iters; i > 0; i-- )
446     {
447         odir = bdir;
448         omx = bmx;
449         omy = bmy;
450         COST_MV_SAD( omx, omy - 2, 0 );
451         COST_MV_SAD( omx, omy + 2, 1 );
452         COST_MV_SAD( omx - 2, omy, 2 );
453         COST_MV_SAD( omx + 2, omy, 3 );
454         if( bmx == omx && bmy == omy )
455             break;
456     }
457     
458     if( !b_refine_qpel )
459     {
460         bcost = COST_MAX;
461         COST_MV_SATD( bmx, bmy, -1 );
462     }
463     
464     /* early termination when examining multiple reference frames */
465     if( p_halfpel_thresh )
466     {
467         if( (bcost*7)>>3 > *p_halfpel_thresh )
468         {
469             m->cost = bcost;
470             m->mv[0] = bmx;
471             m->mv[1] = bmy;
472             // don't need cost_mv
473             return;
474         }
475         else if( bcost < *p_halfpel_thresh )
476             *p_halfpel_thresh = bcost;
477     }
478
479     /* qpel search */
480     bdir = -1;
481     for( i = qpel_iters; i > 0; i-- )
482     {
483         odir = bdir;
484         omx = bmx;
485         omy = bmy;
486         COST_MV_SATD( omx, omy - 1, 0 );
487         COST_MV_SATD( omx, omy + 1, 1 );
488         COST_MV_SATD( omx - 1, omy, 2 );
489         COST_MV_SATD( omx + 1, omy, 3 );
490         if( bmx == omx && bmy == omy )
491             break;
492     }
493
494     m->cost = bcost;
495     m->mv[0] = bmx;
496     m->mv[1] = bmy;
497     m->cost_mv = p_cost_mvx[ bmx ] + p_cost_mvy[ bmy ];
498 }
499
500 #define BIME_CACHE( dx, dy ) \
501 { \
502     int i = 4 + 3*dx + dy; \
503     h->mc.mc_luma( m0->p_fref, m0->i_stride[0], pix0[i], bw, om0x+dx, om0y+dy, bw, bh ); \
504     h->mc.mc_luma( m1->p_fref, m1->i_stride[0], pix1[i], bw, om1x+dx, om1y+dy, bw, bh ); \
505 }
506
507 #define BIME_CACHE2(a,b) \
508     BIME_CACHE(a,b) \
509     BIME_CACHE(-(a),-(b))
510
511 #define COST_BIMV_SATD( m0x, m0y, m1x, m1y ) \
512 if( pass == 0 || !visited[(m0x)&7][(m0y)&7][(m1x)&7][(m1y)&7] ) \
513 { \
514     int cost; \
515     int i0 = 4 + 3*(m0x-om0x) + (m0y-om0y); \
516     int i1 = 4 + 3*(m1x-om1x) + (m1y-om1y); \
517     visited[(m0x)&7][(m0y)&7][(m1x)&7][(m1y)&7] = 1; \
518     memcpy( pix, pix0[i0], bs ); \
519     if( i_weight == 32 ) \
520         h->mc.avg[i_pixel]( pix, bw, pix1[i1], bw ); \
521     else \
522         h->mc.avg_weight[i_pixel]( pix, bw, pix1[i1], bw, i_weight ); \
523     cost = h->pixf.mbcmp[i_pixel]( m0->p_fenc[0], m0->i_stride[0], pix, bw ) \
524          + p_cost_m0x[ m0x ] + p_cost_m0y[ m0y ] \
525          + p_cost_m1x[ m1x ] + p_cost_m1y[ m1y ]; \
526     if( cost < bcost ) \
527     {                  \
528         bcost = cost;  \
529         bm0x = m0x;    \
530         bm0y = m0y;    \
531         bm1x = m1x;    \
532         bm1y = m1y;    \
533     } \
534 }
535
536 #define CHECK_BIDIR(a,b,c,d) \
537     COST_BIMV_SATD(om0x+a, om0y+b, om1x+c, om1y+d)
538
539 #define CHECK_BIDIR2(a,b,c,d) \
540     CHECK_BIDIR(a,b,c,d) \
541     CHECK_BIDIR(-(a),-(b),-(c),-(d))
542
543 #define CHECK_BIDIR8(a,b,c,d) \
544     CHECK_BIDIR2(a,b,c,d) \
545     CHECK_BIDIR2(b,c,d,a) \
546     CHECK_BIDIR2(c,d,a,b) \
547     CHECK_BIDIR2(d,a,b,c)
548
549 int x264_me_refine_bidir( x264_t *h, x264_me_t *m0, x264_me_t *m1, int i_weight )
550 {
551     const int i_pixel = m0->i_pixel;
552     const int bw = x264_pixel_size[i_pixel].w;
553     const int bh = x264_pixel_size[i_pixel].h;
554     const int bs = bw*bh;
555     const int16_t *p_cost_m0x = m0->p_cost_mv - x264_clip3( m0->mvp[0], h->mb.mv_min[0], h->mb.mv_max[0] );
556     const int16_t *p_cost_m0y = m0->p_cost_mv - x264_clip3( m0->mvp[1], h->mb.mv_min[0], h->mb.mv_max[0] );
557     const int16_t *p_cost_m1x = m1->p_cost_mv - x264_clip3( m1->mvp[0], h->mb.mv_min[0], h->mb.mv_max[0] );
558     const int16_t *p_cost_m1y = m1->p_cost_mv - x264_clip3( m1->mvp[1], h->mb.mv_min[0], h->mb.mv_max[0] );
559     DECLARE_ALIGNED( uint8_t, pix0[9][16*16], 16 );
560     DECLARE_ALIGNED( uint8_t, pix1[9][16*16], 16 );
561     DECLARE_ALIGNED( uint8_t, pix[16*16], 16 );
562     int bm0x = m0->mv[0], om0x = bm0x;
563     int bm0y = m0->mv[1], om0y = bm0y;
564     int bm1x = m1->mv[0], om1x = bm1x;
565     int bm1y = m1->mv[1], om1y = bm1y;
566     int bcost = COST_MAX;
567     int pass = 0;
568     uint8_t visited[8][8][8][8];
569     memset( visited, 0, sizeof(visited) );
570
571     BIME_CACHE( 0, 0 );
572     CHECK_BIDIR( 0, 0, 0, 0 );
573
574     for( pass = 0; pass < 8; pass++ )
575     {
576         /* check all mv pairs that differ in at most 2 components from the current mvs. */
577         /* doesn't do chroma ME. this probably doesn't matter, as the gains
578          * from bidir ME are the same with and without chroma ME. */
579
580         BIME_CACHE2( 1, 0 );
581         BIME_CACHE2( 0, 1 );
582         BIME_CACHE2( 1, 1 );
583         BIME_CACHE2( 1,-1 );
584
585         CHECK_BIDIR8( 0, 0, 0, 1 );
586         CHECK_BIDIR8( 0, 0, 1, 1 );
587         CHECK_BIDIR2( 0, 1, 0, 1 );
588         CHECK_BIDIR2( 1, 0, 1, 0 );
589         CHECK_BIDIR8( 0, 0,-1, 1 );
590         CHECK_BIDIR2( 0,-1, 0, 1 );
591         CHECK_BIDIR2(-1, 0, 1, 0 );
592
593         if( om0x == bm0x && om0y == bm0y && om1x == bm1x && om1y == bm1y )
594             break;
595
596         om0x = bm0x;
597         om0y = bm0y;
598         om1x = bm1x;
599         om1y = bm1y;
600         BIME_CACHE( 0, 0 );
601     }
602
603     m0->mv[0] = bm0x;
604     m0->mv[1] = bm0y;
605     m1->mv[0] = bm1x;
606     m1->mv[1] = bm1y;
607     return bcost;
608 }