static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,

                                       int src_index, int ref_index, int const penalty_factor,

                                       int size, int h, int flags)

{

    MotionEstContext * const c= &s->me;

    me_cmp_func cmpf, chroma_cmpf;

    Minima minima[MAX_SAB_SIZE];

    const int minima_count= FFABS(c->dia_size);

    int i, j;

    LOAD_COMMON

    LOAD_COMMON2

    int map_generation= c->map_generation;



    cmpf= s->dsp.me_cmp[size];

    chroma_cmpf= s->dsp.me_cmp[size+1];



    for(j=i=0; i<ME_MAP_SIZE; i++){

        uint32_t key= map[i];



        key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));



        if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;



        assert(j<MAX_SAB_SIZE); 



        minima[j].height= score_map[i];

        minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;

        minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);

        minima[j].x-= (1<<(ME_MAP_MV_BITS-1));

        minima[j].y-= (1<<(ME_MAP_MV_BITS-1));

        minima[j].checked=0;

        if(minima[j].x || minima[j].y)

            minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;



        j++;

    }



    qsort(minima, j, sizeof(Minima), minima_cmp);



    for(; j<minima_count; j++){

        minima[j].height=256*256*256*64;

        minima[j].checked=0;

        minima[j].x= minima[j].y=0;

    }



    for(i=0; i<minima_count; i++){

        const int x= minima[i].x;

        const int y= minima[i].y;

        int d;



        if(minima[i].checked) continue;



        if(   x >= xmax || x <= xmin

           || y >= ymax || y <= ymin)

           continue;



        SAB_CHECK_MV(x-1, y)

        SAB_CHECK_MV(x+1, y)

        SAB_CHECK_MV(x  , y-1)

        SAB_CHECK_MV(x  , y+1)



        minima[i].checked= 1;

    }



    best[0]= minima[0].x;

    best[1]= minima[0].y;

    dmin= minima[0].height;



    if(   best[0] < xmax && best[0] > xmin

       && best[1] < ymax && best[1] > ymin){

        int d;

        

        CHECK_MV(best[0]-1, best[1])

        CHECK_MV(best[0]+1, best[1])

        CHECK_MV(best[0], best[1]-1)

        CHECK_MV(best[0], best[1]+1)

    }

    return dmin;

}
