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