+static void x264_mb_analyse_inter_b8x8_mixed_ref( x264_t *h, x264_mb_analysis_t *a )
+{
+ ALIGNED_ARRAY_8( uint8_t, pix,[2],[8*8] );
+ int i_maxref[2] = {h->mb.pic.i_fref[0]-1, h->mb.pic.i_fref[1]-1};
+
+ /* early termination: if 16x16 chose ref 0, then evalute no refs older
+ * than those used by the neighbors */
+ #define CHECK_NEIGHBOUR(i)\
+ {\
+ int ref = h->mb.cache.ref[l][X264_SCAN8_0+i];\
+ if( ref > i_maxref[l] )\
+ i_maxref[l] = ref;\
+ }
+
+ for( int l = 0; l < 2; l++ )
+ {
+ x264_mb_analysis_list_t *lX = l ? &a->l1 : &a->l0;
+ if( i_maxref[l] > 0 && lX->me16x16.i_ref == 0 &&
+ h->mb.i_mb_type_top > 0 && h->mb.i_mb_type_left > 0 )
+ {
+ i_maxref[l] = 0;
+ CHECK_NEIGHBOUR( -8 - 1 );
+ CHECK_NEIGHBOUR( -8 + 0 );
+ CHECK_NEIGHBOUR( -8 + 2 );
+ CHECK_NEIGHBOUR( -8 + 4 );
+ CHECK_NEIGHBOUR( 0 - 1 );
+ CHECK_NEIGHBOUR( 2*8 - 1 );
+ }
+ }
+
+ /* XXX Needed for x264_mb_predict_mv */
+ h->mb.i_partition = D_8x8;
+
+ a->i_cost8x8bi = 0;
+
+ for( int i = 0; i < 4; i++ )
+ {
+ int x8 = i%2;
+ int y8 = i/2;
+ int i_part_cost;
+ int i_part_cost_bi;
+ int stride[2] = {8,8};
+ uint8_t *src[2];
+ x264_me_t m;
+ m.i_pixel = PIXEL_8x8;
+ LOAD_FENC( &m, h->mb.pic.p_fenc, 8*x8, 8*y8 );
+
+ for( int l = 0; l < 2; l++ )
+ {
+ x264_mb_analysis_list_t *lX = l ? &a->l1 : &a->l0;
+
+ lX->me8x8[i].cost = INT_MAX;
+ for( int i_ref = 0; i_ref <= i_maxref[l]; i_ref++ )
+ {
+ m.i_ref_cost = REF_COST( l, i_ref );;
+
+ LOAD_HPELS( &m, h->mb.pic.p_fref[l][i_ref], l, i_ref, 8*x8, 8*y8 );
+
+ x264_macroblock_cache_ref( h, x8*2, y8*2, 2, 2, l, i_ref );
+ x264_mb_predict_mv( h, l, 4*i, 2, m.mvp );
+ x264_me_search( h, &m, lX->mvc[i_ref], i+1 );
+ m.cost += m.i_ref_cost;
+
+ if( m.cost < lX->me8x8[i].cost )
+ h->mc.memcpy_aligned( &lX->me8x8[i], &m, sizeof(x264_me_t) );
+
+ /* save mv for predicting other partitions within this MB */
+ CP32( lX->mvc[i_ref][i+1], m.mv );
+ }
+ }
+
+ /* BI mode */
+ src[0] = h->mc.get_ref( pix[0], &stride[0], a->l0.me8x8[i].p_fref, a->l0.me8x8[i].i_stride[0],
+ a->l0.me8x8[i].mv[0], a->l0.me8x8[i].mv[1], 8, 8, weight_none );
+ src[1] = h->mc.get_ref( pix[1], &stride[1], a->l1.me8x8[i].p_fref, a->l1.me8x8[i].i_stride[0],
+ a->l1.me8x8[i].mv[0], a->l1.me8x8[i].mv[1], 8, 8, weight_none );
+ h->mc.avg[PIXEL_8x8]( pix[0], 8, src[0], stride[0], src[1], stride[1],
+ h->mb.bipred_weight[a->l0.me8x8[i].i_ref][a->l1.me8x8[i].i_ref] );
+
+ i_part_cost_bi = h->pixf.mbcmp[PIXEL_8x8]( a->l0.me8x8[i].p_fenc[0], FENC_STRIDE, pix[0], 8 )
+ + a->l0.me8x8[i].cost_mv + a->l1.me8x8[i].cost_mv + a->l0.me8x8[i].i_ref_cost
+ + a->l1.me8x8[i].i_ref_cost + a->i_lambda * i_sub_mb_b_cost_table[D_BI_8x8];
+
+ a->l0.me8x8[i].cost += a->i_lambda * i_sub_mb_b_cost_table[D_L0_8x8];
+ a->l1.me8x8[i].cost += a->i_lambda * i_sub_mb_b_cost_table[D_L1_8x8];
+
+ i_part_cost = a->l0.me8x8[i].cost;
+ h->mb.i_sub_partition[i] = D_L0_8x8;
+ COPY2_IF_LT( i_part_cost, a->l1.me8x8[i].cost, h->mb.i_sub_partition[i], D_L1_8x8 );
+ COPY2_IF_LT( i_part_cost, i_part_cost_bi, h->mb.i_sub_partition[i], D_BI_8x8 );
+ COPY2_IF_LT( i_part_cost, a->i_cost8x8direct[i], h->mb.i_sub_partition[i], D_DIRECT_8x8 );
+ a->i_cost8x8bi += i_part_cost;
+
+ /* XXX Needed for x264_mb_predict_mv */
+ x264_mb_cache_mv_b8x8( h, a, i, 0 );
+ }
+
+ /* mb type cost */
+ a->i_cost8x8bi += a->i_lambda * i_mb_b_cost_table[B_8x8];
+}
+