static void iterative_me(SnowContext *s){

    int pass, mb_x, mb_y;

    const int b_width = s->b_width  << s->block_max_depth;

    const int b_height= s->b_height << s->block_max_depth;

    const int b_stride= b_width;

    int color[3];



    for(pass=0; pass<50; pass++){

        int change= 0;



        for(mb_y= 0; mb_y<b_height; mb_y++){

            for(mb_x= 0; mb_x<b_width; mb_x++){

                int dia_change, i, j;

                int best_rd= INT_MAX;

                BlockNode backup;

                const int index= mb_x + mb_y * b_stride;

                BlockNode *block= &s->block[index];

                BlockNode *tb =                 mb_y          ? &s->block[index-b_stride  ] : &null_block;

                BlockNode *lb = mb_x                          ? &s->block[index         -1] : &null_block;

                BlockNode *rb = mb_x<b_width                  ? &s->block[index         +1] : &null_block;

                BlockNode *bb =                 mb_y<b_height ? &s->block[index+b_stride  ] : &null_block;

                BlockNode *tlb= mb_x         && mb_y          ? &s->block[index-b_stride-1] : &null_block;

                BlockNode *trb= mb_x<b_width && mb_y          ? &s->block[index-b_stride+1] : &null_block;

                BlockNode *blb= mb_x         && mb_y<b_height ? &s->block[index+b_stride-1] : &null_block;

                BlockNode *brb= mb_x<b_width && mb_y<b_height ? &s->block[index+b_stride+1] : &null_block;



                if(pass && (block->type & BLOCK_OPT))

                    continue;

                block->type |= BLOCK_OPT;



                backup= *block;



                if(!s->me_cache_generation)

                    memset(s->me_cache, 0, sizeof(s->me_cache));

                s->me_cache_generation += 1<<22;



                // get previous score (cant be cached due to OBMC)

                check_block(s, mb_x, mb_y, (int[2]){block->mx, block->my}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){0, 0}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){tb->mx, tb->my}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){lb->mx, lb->my}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){rb->mx, rb->my}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){bb->mx, bb->my}, 0, &best_rd);



                /* fullpel ME */

                //FIXME avoid subpel interpol / round to nearest integer

                do{

                    dia_change=0;

                    for(i=0; i<FFMAX(s->avctx->dia_size, 1); i++){

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

                            dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx+4*(i-j), block->my+(4*j)}, 0, &best_rd);

                            dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx-4*(i-j), block->my-(4*j)}, 0, &best_rd);

                            dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx+4*(i-j), block->my-(4*j)}, 0, &best_rd);

                            dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx-4*(i-j), block->my+(4*j)}, 0, &best_rd);

                        }

                    }

                }while(dia_change);

                /* subpel ME */

                do{

                    static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},};

                    dia_change=0;

                    for(i=0; i<8; i++)

                        dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx+square[i][0], block->my+square[i][1]}, 0, &best_rd);

                }while(dia_change);

                //FIXME or try the standard 2 pass qpel or similar



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

                    color[i]= get_dc(s, mb_x, mb_y, i);

                }

                check_block(s, mb_x, mb_y, color, 1, &best_rd);

                //FIXME RD style color selection



                if(!same_block(block, &backup)){

                    if(tb != &null_block) tb ->type &= ~BLOCK_OPT;

                    if(lb != &null_block) lb ->type &= ~BLOCK_OPT;

                    if(rb != &null_block) rb ->type &= ~BLOCK_OPT;

                    if(bb != &null_block) bb ->type &= ~BLOCK_OPT;

                    if(tlb!= &null_block) tlb->type &= ~BLOCK_OPT;

                    if(trb!= &null_block) trb->type &= ~BLOCK_OPT;

                    if(blb!= &null_block) blb->type &= ~BLOCK_OPT;

                    if(brb!= &null_block) brb->type &= ~BLOCK_OPT;

                    change ++;

                }

            }

        }

        av_log(NULL, AV_LOG_ERROR, "pass:%d changed:%d\n", pass, change);

        if(!change)

            break;

    }

}

static void iterative_me(SnowContext *s){

    int pass, mb_x, mb_y;

    const int b_width = s->b_width  << s->block_max_depth;

    const int b_height= s->b_height << s->block_max_depth;

    const int b_stride= b_width;

    int color[3];



    for(pass=0; pass<50; pass++){

        int change= 0;



        for(mb_y= 0; mb_y<b_height; mb_y++){

            for(mb_x= 0; mb_x<b_width; mb_x++){

                int dia_change, i, j;

                int best_rd= INT_MAX;

                BlockNode backup;

                const int index= mb_x + mb_y * b_stride;

                BlockNode *block= &s->block[index];

                BlockNode *tb =                 mb_y          ? &s->block[index-b_stride  ] : &null_block;

                BlockNode *lb = mb_x                          ? &s->block[index         -1] : &null_block;

                BlockNode *rb = mb_x<b_width                  ? &s->block[index         +1] : &null_block;

                BlockNode *bb =                 mb_y<b_height ? &s->block[index+b_stride  ] : &null_block;

                BlockNode *tlb= mb_x         && mb_y          ? &s->block[index-b_stride-1] : &null_block;

                BlockNode *trb= mb_x<b_width && mb_y          ? &s->block[index-b_stride+1] : &null_block;

                BlockNode *blb= mb_x         && mb_y<b_height ? &s->block[index+b_stride-1] : &null_block;

                BlockNode *brb= mb_x<b_width && mb_y<b_height ? &s->block[index+b_stride+1] : &null_block;



                if(pass && (block->type & BLOCK_OPT))

                    continue;

                block->type |= BLOCK_OPT;



                backup= *block;



                if(!s->me_cache_generation)

                    memset(s->me_cache, 0, sizeof(s->me_cache));

                s->me_cache_generation += 1<<22;



                

                check_block(s, mb_x, mb_y, (int[2]){block->mx, block->my}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){0, 0}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){tb->mx, tb->my}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){lb->mx, lb->my}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){rb->mx, rb->my}, 0, &best_rd);

                check_block(s, mb_x, mb_y, (int[2]){bb->mx, bb->my}, 0, &best_rd);



                

                

                do{

                    dia_change=0;

                    for(i=0; i<FFMAX(s->avctx->dia_size, 1); i++){

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

                            dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx+4*(i-j), block->my+(4*j)}, 0, &best_rd);

                            dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx-4*(i-j), block->my-(4*j)}, 0, &best_rd);

                            dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx+4*(i-j), block->my-(4*j)}, 0, &best_rd);

                            dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx-4*(i-j), block->my+(4*j)}, 0, &best_rd);

                        }

                    }

                }while(dia_change);

                

                do{

                    static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},};

                    dia_change=0;

                    for(i=0; i<8; i++)

                        dia_change |= check_block(s, mb_x, mb_y, (int[2]){block->mx+square[i][0], block->my+square[i][1]}, 0, &best_rd);

                }while(dia_change);

                



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

                    color[i]= get_dc(s, mb_x, mb_y, i);

                }

                check_block(s, mb_x, mb_y, color, 1, &best_rd);

                



                if(!same_block(block, &backup)){

                    if(tb != &null_block) tb ->type &= ~BLOCK_OPT;

                    if(lb != &null_block) lb ->type &= ~BLOCK_OPT;

                    if(rb != &null_block) rb ->type &= ~BLOCK_OPT;

                    if(bb != &null_block) bb ->type &= ~BLOCK_OPT;

                    if(tlb!= &null_block) tlb->type &= ~BLOCK_OPT;

                    if(trb!= &null_block) trb->type &= ~BLOCK_OPT;

                    if(blb!= &null_block) blb->type &= ~BLOCK_OPT;

                    if(brb!= &null_block) brb->type &= ~BLOCK_OPT;

                    change ++;

                }

            }

        }

        av_log(NULL, AV_LOG_ERROR, "pass:%d changed:%d\n", pass, change);

        if(!change)

            break;

    }

}

static void FUNC_0(SnowContext *VAR_0){

    int VAR_1, VAR_2, VAR_3;

    const int VAR_4 = VAR_0->VAR_4  << VAR_0->block_max_depth;

    const int VAR_5= VAR_0->VAR_5 << VAR_0->block_max_depth;

    const int VAR_6= VAR_4;

    int VAR_7[3];



    for(VAR_1=0; VAR_1<50; VAR_1++){

        int VAR_8= 0;



        for(VAR_3= 0; VAR_3<VAR_5; VAR_3++){

            for(VAR_2= 0; VAR_2<VAR_4; VAR_2++){

                int VAR_9, VAR_10, VAR_11;

                int VAR_12= INT_MAX;

                BlockNode backup;

                const int VAR_13= VAR_2 + VAR_3 * VAR_6;

                BlockNode *block= &VAR_0->block[VAR_13];

                BlockNode *tb =                 VAR_3          ? &VAR_0->block[VAR_13-VAR_6  ] : &null_block;

                BlockNode *lb = VAR_2                          ? &VAR_0->block[VAR_13         -1] : &null_block;

                BlockNode *rb = VAR_2<VAR_4                  ? &VAR_0->block[VAR_13         +1] : &null_block;

                BlockNode *bb =                 VAR_3<VAR_5 ? &VAR_0->block[VAR_13+VAR_6  ] : &null_block;

                BlockNode *tlb= VAR_2         && VAR_3          ? &VAR_0->block[VAR_13-VAR_6-1] : &null_block;

                BlockNode *trb= VAR_2<VAR_4 && VAR_3          ? &VAR_0->block[VAR_13-VAR_6+1] : &null_block;

                BlockNode *blb= VAR_2         && VAR_3<VAR_5 ? &VAR_0->block[VAR_13+VAR_6-1] : &null_block;

                BlockNode *brb= VAR_2<VAR_4 && VAR_3<VAR_5 ? &VAR_0->block[VAR_13+VAR_6+1] : &null_block;



                if(VAR_1 && (block->type & BLOCK_OPT))

                    continue;

                block->type |= BLOCK_OPT;



                backup= *block;



                if(!VAR_0->me_cache_generation)

                    memset(VAR_0->me_cache, 0, sizeof(VAR_0->me_cache));

                VAR_0->me_cache_generation += 1<<22;



                

                check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx, block->my}, 0, &VAR_12);

                check_block(VAR_0, VAR_2, VAR_3, (int[2]){0, 0}, 0, &VAR_12);

                check_block(VAR_0, VAR_2, VAR_3, (int[2]){tb->mx, tb->my}, 0, &VAR_12);

                check_block(VAR_0, VAR_2, VAR_3, (int[2]){lb->mx, lb->my}, 0, &VAR_12);

                check_block(VAR_0, VAR_2, VAR_3, (int[2]){rb->mx, rb->my}, 0, &VAR_12);

                check_block(VAR_0, VAR_2, VAR_3, (int[2]){bb->mx, bb->my}, 0, &VAR_12);



                

                

                do{

                    VAR_9=0;

                    for(VAR_10=0; VAR_10<FFMAX(VAR_0->avctx->dia_size, 1); VAR_10++){

                        for(VAR_11=0; VAR_11<VAR_10; VAR_11++){

                            VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx+4*(VAR_10-VAR_11), block->my+(4*VAR_11)}, 0, &VAR_12);

                            VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx-4*(VAR_10-VAR_11), block->my-(4*VAR_11)}, 0, &VAR_12);

                            VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx+4*(VAR_10-VAR_11), block->my-(4*VAR_11)}, 0, &VAR_12);

                            VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx-4*(VAR_10-VAR_11), block->my+(4*VAR_11)}, 0, &VAR_12);

                        }

                    }

                }while(VAR_9);

                

                do{

                    static const int VAR_14[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},};

                    VAR_9=0;

                    for(VAR_10=0; VAR_10<8; VAR_10++)

                        VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx+VAR_14[VAR_10][0], block->my+VAR_14[VAR_10][1]}, 0, &VAR_12);

                }while(VAR_9);

                



                for(VAR_10=0; VAR_10<3; VAR_10++){

                    VAR_7[VAR_10]= get_dc(VAR_0, VAR_2, VAR_3, VAR_10);

                }

                check_block(VAR_0, VAR_2, VAR_3, VAR_7, 1, &VAR_12);

                



                if(!same_block(block, &backup)){

                    if(tb != &null_block) tb ->type &= ~BLOCK_OPT;

                    if(lb != &null_block) lb ->type &= ~BLOCK_OPT;

                    if(rb != &null_block) rb ->type &= ~BLOCK_OPT;

                    if(bb != &null_block) bb ->type &= ~BLOCK_OPT;

                    if(tlb!= &null_block) tlb->type &= ~BLOCK_OPT;

                    if(trb!= &null_block) trb->type &= ~BLOCK_OPT;

                    if(blb!= &null_block) blb->type &= ~BLOCK_OPT;

                    if(brb!= &null_block) brb->type &= ~BLOCK_OPT;

                    VAR_8 ++;

                }

            }

        }

        av_log(NULL, AV_LOG_ERROR, "VAR_1:%d changed:%d\n", VAR_1, VAR_8);

        if(!VAR_8)

            break;

    }

}

static void FUNC_0(SnowContext *VAR_0){ int VAR_1, VAR_2, VAR_3; const int VAR_4 = VAR_0->VAR_4  << VAR_0->block_max_depth; const int VAR_5= VAR_0->VAR_5 << VAR_0->block_max_depth; const int VAR_6= VAR_4; int VAR_7[3]; for(VAR_1=0; VAR_1<50; VAR_1++){ int VAR_8= 0; for(VAR_3= 0; VAR_3<VAR_5; VAR_3++){ for(VAR_2= 0; VAR_2<VAR_4; VAR_2++){ int VAR_9, VAR_10, VAR_11; int VAR_12= INT_MAX; BlockNode backup; const int VAR_13= VAR_2 + VAR_3 * VAR_6; BlockNode *block= &VAR_0->block[VAR_13]; BlockNode *tb =                 VAR_3          ? &VAR_0->block[VAR_13-VAR_6  ] : &null_block; BlockNode *lb = VAR_2                          ? &VAR_0->block[VAR_13         -1] : &null_block; BlockNode *rb = VAR_2<VAR_4                  ? &VAR_0->block[VAR_13         +1] : &null_block; BlockNode *bb =                 VAR_3<VAR_5 ? &VAR_0->block[VAR_13+VAR_6  ] : &null_block; BlockNode *tlb= VAR_2         && VAR_3          ? &VAR_0->block[VAR_13-VAR_6-1] : &null_block; BlockNode *trb= VAR_2<VAR_4 && VAR_3          ? &VAR_0->block[VAR_13-VAR_6+1] : &null_block; BlockNode *blb= VAR_2         && VAR_3<VAR_5 ? &VAR_0->block[VAR_13+VAR_6-1] : &null_block; BlockNode *brb= VAR_2<VAR_4 && VAR_3<VAR_5 ? &VAR_0->block[VAR_13+VAR_6+1] : &null_block; if(VAR_1 && (block->type & BLOCK_OPT))
continue; block->type |= BLOCK_OPT; backup= *block; if(!VAR_0->me_cache_generation)
memset(VAR_0->me_cache, 0, sizeof(VAR_0->me_cache)); VAR_0->me_cache_generation += 1<<22; check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx, block->my}, 0, &VAR_12); check_block(VAR_0, VAR_2, VAR_3, (int[2]){0, 0}, 0, &VAR_12); check_block(VAR_0, VAR_2, VAR_3, (int[2]){tb->mx, tb->my}, 0, &VAR_12); check_block(VAR_0, VAR_2, VAR_3, (int[2]){lb->mx, lb->my}, 0, &VAR_12); check_block(VAR_0, VAR_2, VAR_3, (int[2]){rb->mx, rb->my}, 0, &VAR_12); check_block(VAR_0, VAR_2, VAR_3, (int[2]){bb->mx, bb->my}, 0, &VAR_12); do{ VAR_9=0; for(VAR_10=0; VAR_10<FFMAX(VAR_0->avctx->dia_size, 1); VAR_10++){ for(VAR_11=0; VAR_11<VAR_10; VAR_11++){ VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx+4*(VAR_10-VAR_11), block->my+(4*VAR_11)}, 0, &VAR_12); VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx-4*(VAR_10-VAR_11), block->my-(4*VAR_11)}, 0, &VAR_12); VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx+4*(VAR_10-VAR_11), block->my-(4*VAR_11)}, 0, &VAR_12); VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx-4*(VAR_10-VAR_11), block->my+(4*VAR_11)}, 0, &VAR_12); } } }while(VAR_9); do{ static const int VAR_14[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},}; VAR_9=0; for(VAR_10=0; VAR_10<8; VAR_10++) VAR_9 |= check_block(VAR_0, VAR_2, VAR_3, (int[2]){block->mx+VAR_14[VAR_10][0], block->my+VAR_14[VAR_10][1]}, 0, &VAR_12); }while(VAR_9); for(VAR_10=0; VAR_10<3; VAR_10++){ VAR_7[VAR_10]= get_dc(VAR_0, VAR_2, VAR_3, VAR_10); } check_block(VAR_0, VAR_2, VAR_3, VAR_7, 1, &VAR_12); if(!same_block(block, &backup)){ if(tb != &null_block) tb ->type &= ~BLOCK_OPT; if(lb != &null_block) lb ->type &= ~BLOCK_OPT; if(rb != &null_block) rb ->type &= ~BLOCK_OPT; if(bb != &null_block) bb ->type &= ~BLOCK_OPT; if(tlb!= &null_block) tlb->type &= ~BLOCK_OPT; if(trb!= &null_block) trb->type &= ~BLOCK_OPT; if(blb!= &null_block) blb->type &= ~BLOCK_OPT; if(brb!= &null_block) brb->type &= ~BLOCK_OPT; VAR_8 ++; } } } av_log(NULL, AV_LOG_ERROR, "VAR_1:%d changed:%d\n", VAR_1, VAR_8); if(!VAR_8)
break; } }