static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, uint8_t *decoded, int stride, int level, int threshold, int lambda, int intra){

    int count, y, x, i, j, split, best_mean, best_score, best_count;

    int best_vector[6];

    int block_sum[7]= {0, 0, 0, 0, 0, 0};

    int w= 2<<((level+2)>>1);

    int h= 2<<((level+1)>>1);

    int size=w*h;

    int16_t block[7][256];

    const int8_t *codebook_sum, *codebook;

    const uint16_t (*mean_vlc)[2];

    const uint8_t (*multistage_vlc)[2];



    best_score=0;

    //FIXME optimize, this doenst need to be done multiple times

    if(intra){

        codebook_sum= svq1_intra_codebook_sum[level];

        codebook= svq1_intra_codebooks[level];

        mean_vlc= svq1_intra_mean_vlc;

        multistage_vlc= svq1_intra_multistage_vlc[level];

        for(y=0; y<h; y++){

            for(x=0; x<w; x++){

                int v= src[x + y*stride];

                block[0][x + w*y]= v;

                best_score += v*v;

                block_sum[0] += v;

            }

        }

    }else{

        codebook_sum= svq1_inter_codebook_sum[level];

        codebook= svq1_inter_codebooks[level];

        mean_vlc= svq1_inter_mean_vlc + 256;

        multistage_vlc= svq1_inter_multistage_vlc[level];

        for(y=0; y<h; y++){

            for(x=0; x<w; x++){

                int v= src[x + y*stride] - ref[x + y*stride];

                block[0][x + w*y]= v;

                best_score += v*v;

                block_sum[0] += v;

            }

        }

    }



    best_count=0;

    best_score -= ((block_sum[0]*block_sum[0])>>(level+3));

    best_mean= (block_sum[0] + (size>>1)) >> (level+3);



    if(level<4){

        for(count=1; count<7; count++){

            int best_vector_score= INT_MAX;

            int best_vector_sum=-999, best_vector_mean=-999;

            const int stage= count-1;

            const int8_t *vector;



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

                int sum= codebook_sum[stage*16 + i];

                int sqr, diff, mean, score;



                vector = codebook + stage*size*16 + i*size;

                sqr = s->dsp.ssd_int8_vs_int16(vector, block[stage], size);

                diff= block_sum[stage] - sum;

                mean= (diff + (size>>1)) >> (level+3);

                assert(mean >-300 && mean<300);

                if(intra) mean= av_clip(mean, 0, 255);

                else      mean= av_clip(mean, -256, 255);

                score= sqr - ((diff*(int64_t)diff)>>(level+3)); //FIXME 64bit slooow

                if(score < best_vector_score){

                    best_vector_score= score;

                    best_vector[stage]= i;

                    best_vector_sum= sum;

                    best_vector_mean= mean;

                }

            }

            assert(best_vector_mean != -999);

            vector= codebook + stage*size*16 + best_vector[stage]*size;

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

                block[stage+1][j] = block[stage][j] - vector[j];

            }

            block_sum[stage+1]= block_sum[stage] - best_vector_sum;

            best_vector_score +=

                lambda*(+ 1 + 4*count

                        + multistage_vlc[1+count][1]

                        + mean_vlc[best_vector_mean][1]);



            if(best_vector_score < best_score){

                best_score= best_vector_score;

                best_count= count;

                best_mean= best_vector_mean;

            }

        }

    }



    split=0;

    if(best_score > threshold && level){

        int score=0;

        int offset= (level&1) ? stride*h/2 : w/2;

        PutBitContext backup[6];



        for(i=level-1; i>=0; i--){

            backup[i]= s->reorder_pb[i];

        }

        score += encode_block(s, src         , ref         , decoded         , stride, level-1, threshold>>1, lambda, intra);

        score += encode_block(s, src + offset, ref + offset, decoded + offset, stride, level-1, threshold>>1, lambda, intra);

        score += lambda;



        if(score < best_score){

            best_score= score;

            split=1;

        }else{

            for(i=level-1; i>=0; i--){

                s->reorder_pb[i]= backup[i];

            }

        }

    }

    if (level > 0)

        put_bits(&s->reorder_pb[level], 1, split);



    if(!split){

        assert((best_mean >= 0 && best_mean<256) || !intra);

        assert(best_mean >= -256 && best_mean<256);

        assert(best_count >=0 && best_count<7);

        assert(level<4 || best_count==0);



        /* output the encoding */

        put_bits(&s->reorder_pb[level],

            multistage_vlc[1 + best_count][1],

            multistage_vlc[1 + best_count][0]);

        put_bits(&s->reorder_pb[level], mean_vlc[best_mean][1],

            mean_vlc[best_mean][0]);



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

            assert(best_vector[i]>=0 && best_vector[i]<16);

            put_bits(&s->reorder_pb[level], 4, best_vector[i]);

        }



        for(y=0; y<h; y++){

            for(x=0; x<w; x++){

                decoded[x + y*stride]= src[x + y*stride] - block[best_count][x + w*y] + best_mean;

            }

        }

    }



    return best_score;

}

static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, uint8_t *decoded, int stride, int level, int threshold, int lambda, int intra){

    int count, y, x, i, j, split, best_mean, best_score, best_count;

    int best_vector[6];

    int block_sum[7]= {0, 0, 0, 0, 0, 0};

    int w= 2<<((level+2)>>1);

    int h= 2<<((level+1)>>1);

    int size=w*h;

    int16_t block[7][256];

    const int8_t *codebook_sum, *codebook;

    const uint16_t (*mean_vlc)[2];

    const uint8_t (*multistage_vlc)[2];



    best_score=0;

    

    if(intra){

        codebook_sum= svq1_intra_codebook_sum[level];

        codebook= svq1_intra_codebooks[level];

        mean_vlc= svq1_intra_mean_vlc;

        multistage_vlc= svq1_intra_multistage_vlc[level];

        for(y=0; y<h; y++){

            for(x=0; x<w; x++){

                int v= src[x + y*stride];

                block[0][x + w*y]= v;

                best_score += v*v;

                block_sum[0] += v;

            }

        }

    }else{

        codebook_sum= svq1_inter_codebook_sum[level];

        codebook= svq1_inter_codebooks[level];

        mean_vlc= svq1_inter_mean_vlc + 256;

        multistage_vlc= svq1_inter_multistage_vlc[level];

        for(y=0; y<h; y++){

            for(x=0; x<w; x++){

                int v= src[x + y*stride] - ref[x + y*stride];

                block[0][x + w*y]= v;

                best_score += v*v;

                block_sum[0] += v;

            }

        }

    }



    best_count=0;

    best_score -= ((block_sum[0]*block_sum[0])>>(level+3));

    best_mean= (block_sum[0] + (size>>1)) >> (level+3);



    if(level<4){

        for(count=1; count<7; count++){

            int best_vector_score= INT_MAX;

            int best_vector_sum=-999, best_vector_mean=-999;

            const int stage= count-1;

            const int8_t *vector;



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

                int sum= codebook_sum[stage*16 + i];

                int sqr, diff, mean, score;



                vector = codebook + stage*size*16 + i*size;

                sqr = s->dsp.ssd_int8_vs_int16(vector, block[stage], size);

                diff= block_sum[stage] - sum;

                mean= (diff + (size>>1)) >> (level+3);

                assert(mean >-300 && mean<300);

                if(intra) mean= av_clip(mean, 0, 255);

                else      mean= av_clip(mean, -256, 255);

                score= sqr - ((diff*(int64_t)diff)>>(level+3)); 

                if(score < best_vector_score){

                    best_vector_score= score;

                    best_vector[stage]= i;

                    best_vector_sum= sum;

                    best_vector_mean= mean;

                }

            }

            assert(best_vector_mean != -999);

            vector= codebook + stage*size*16 + best_vector[stage]*size;

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

                block[stage+1][j] = block[stage][j] - vector[j];

            }

            block_sum[stage+1]= block_sum[stage] - best_vector_sum;

            best_vector_score +=

                lambda*(+ 1 + 4*count

                        + multistage_vlc[1+count][1]

                        + mean_vlc[best_vector_mean][1]);



            if(best_vector_score < best_score){

                best_score= best_vector_score;

                best_count= count;

                best_mean= best_vector_mean;

            }

        }

    }



    split=0;

    if(best_score > threshold && level){

        int score=0;

        int offset= (level&1) ? stride*h/2 : w/2;

        PutBitContext backup[6];



        for(i=level-1; i>=0; i--){

            backup[i]= s->reorder_pb[i];

        }

        score += encode_block(s, src         , ref         , decoded         , stride, level-1, threshold>>1, lambda, intra);

        score += encode_block(s, src + offset, ref + offset, decoded + offset, stride, level-1, threshold>>1, lambda, intra);

        score += lambda;



        if(score < best_score){

            best_score= score;

            split=1;

        }else{

            for(i=level-1; i>=0; i--){

                s->reorder_pb[i]= backup[i];

            }

        }

    }

    if (level > 0)

        put_bits(&s->reorder_pb[level], 1, split);



    if(!split){

        assert((best_mean >= 0 && best_mean<256) || !intra);

        assert(best_mean >= -256 && best_mean<256);

        assert(best_count >=0 && best_count<7);

        assert(level<4 || best_count==0);



        

        put_bits(&s->reorder_pb[level],

            multistage_vlc[1 + best_count][1],

            multistage_vlc[1 + best_count][0]);

        put_bits(&s->reorder_pb[level], mean_vlc[best_mean][1],

            mean_vlc[best_mean][0]);



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

            assert(best_vector[i]>=0 && best_vector[i]<16);

            put_bits(&s->reorder_pb[level], 4, best_vector[i]);

        }



        for(y=0; y<h; y++){

            for(x=0; x<w; x++){

                decoded[x + y*stride]= src[x + y*stride] - block[best_count][x + w*y] + best_mean;

            }

        }

    }



    return best_score;

}

static int FUNC_0(SVQ1Context *VAR_0, FUNC_2 *VAR_1, FUNC_2 *VAR_2, FUNC_2 *VAR_3, int VAR_4, int VAR_5, int VAR_6, int VAR_7, int VAR_8){

    int VAR_9, VAR_10, VAR_11, VAR_12, VAR_13, VAR_14, VAR_15, VAR_16, VAR_17;

    int VAR_18[6];

    int VAR_19[7]= {0, 0, 0, 0, 0, 0};

    int VAR_20= 2<<((VAR_5+2)>>1);

    int VAR_21= 2<<((VAR_5+1)>>1);

    int VAR_22=VAR_20*VAR_21;

    int16_t block[7][256];

    const int8_t *VAR_23, *codebook;

    const FUNC_1 (*mean_vlc)[2];

    const FUNC_2 (*multistage_vlc)[2];



    VAR_16=0;

    

    if(VAR_8){

        VAR_23= svq1_intra_codebook_sum[VAR_5];

        codebook= svq1_intra_codebooks[VAR_5];

        mean_vlc= svq1_intra_mean_vlc;

        multistage_vlc= svq1_intra_multistage_vlc[VAR_5];

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

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

                int VAR_25= VAR_1[VAR_11 + VAR_10*VAR_4];

                block[0][VAR_11 + VAR_20*VAR_10]= VAR_25;

                VAR_16 += VAR_25*VAR_25;

                VAR_19[0] += VAR_25;

            }

        }

    }else{

        VAR_23= svq1_inter_codebook_sum[VAR_5];

        codebook= svq1_inter_codebooks[VAR_5];

        mean_vlc= svq1_inter_mean_vlc + 256;

        multistage_vlc= svq1_inter_multistage_vlc[VAR_5];

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

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

                int VAR_25= VAR_1[VAR_11 + VAR_10*VAR_4] - VAR_2[VAR_11 + VAR_10*VAR_4];

                block[0][VAR_11 + VAR_20*VAR_10]= VAR_25;

                VAR_16 += VAR_25*VAR_25;

                VAR_19[0] += VAR_25;

            }

        }

    }



    VAR_17=0;

    VAR_16 -= ((VAR_19[0]*VAR_19[0])>>(VAR_5+3));

    VAR_15= (VAR_19[0] + (VAR_22>>1)) >> (VAR_5+3);



    if(VAR_5<4){

        for(VAR_9=1; VAR_9<7; VAR_9++){

            int VAR_25= INT_MAX;

            int VAR_26=-999, VAR_27=-999;

            const int VAR_28= VAR_9-1;

            const int8_t *VAR_29;



            for(VAR_12=0; VAR_12<16; VAR_12++){

                int VAR_30= VAR_23[VAR_28*16 + VAR_12];

                int VAR_31, VAR_32, VAR_33, VAR_35;



                VAR_29 = codebook + VAR_28*VAR_22*16 + VAR_12*VAR_22;

                VAR_31 = VAR_0->dsp.ssd_int8_vs_int16(VAR_29, block[VAR_28], VAR_22);

                VAR_32= VAR_19[VAR_28] - VAR_30;

                VAR_33= (VAR_32 + (VAR_22>>1)) >> (VAR_5+3);

                assert(VAR_33 >-300 && VAR_33<300);

                if(VAR_8) VAR_33= av_clip(VAR_33, 0, 255);

                else      VAR_33= av_clip(VAR_33, -256, 255);

                VAR_35= VAR_31 - ((VAR_32*(int64_t)VAR_32)>>(VAR_5+3)); 

                if(VAR_35 < VAR_25){

                    VAR_25= VAR_35;

                    VAR_18[VAR_28]= VAR_12;

                    VAR_26= VAR_30;

                    VAR_27= VAR_33;

                }

            }

            assert(VAR_27 != -999);

            VAR_29= codebook + VAR_28*VAR_22*16 + VAR_18[VAR_28]*VAR_22;

            for(VAR_13=0; VAR_13<VAR_22; VAR_13++){

                block[VAR_28+1][VAR_13] = block[VAR_28][VAR_13] - VAR_29[VAR_13];

            }

            VAR_19[VAR_28+1]= VAR_19[VAR_28] - VAR_26;

            VAR_25 +=

                VAR_7*(+ 1 + 4*VAR_9

                        + multistage_vlc[1+VAR_9][1]

                        + mean_vlc[VAR_27][1]);



            if(VAR_25 < VAR_16){

                VAR_16= VAR_25;

                VAR_17= VAR_9;

                VAR_15= VAR_27;

            }

        }

    }



    VAR_14=0;

    if(VAR_16 > VAR_6 && VAR_5){

        int VAR_35=0;

        int VAR_35= (VAR_5&1) ? VAR_4*VAR_21/2 : VAR_20/2;

        PutBitContext backup[6];



        for(VAR_12=VAR_5-1; VAR_12>=0; VAR_12--){

            backup[VAR_12]= VAR_0->reorder_pb[VAR_12];

        }

        VAR_35 += FUNC_0(VAR_0, VAR_1         , VAR_2         , VAR_3         , VAR_4, VAR_5-1, VAR_6>>1, VAR_7, VAR_8);

        VAR_35 += FUNC_0(VAR_0, VAR_1 + VAR_35, VAR_2 + VAR_35, VAR_3 + VAR_35, VAR_4, VAR_5-1, VAR_6>>1, VAR_7, VAR_8);

        VAR_35 += VAR_7;



        if(VAR_35 < VAR_16){

            VAR_16= VAR_35;

            VAR_14=1;

        }else{

            for(VAR_12=VAR_5-1; VAR_12>=0; VAR_12--){

                VAR_0->reorder_pb[VAR_12]= backup[VAR_12];

            }

        }

    }

    if (VAR_5 > 0)

        put_bits(&VAR_0->reorder_pb[VAR_5], 1, VAR_14);



    if(!VAR_14){

        assert((VAR_15 >= 0 && VAR_15<256) || !VAR_8);

        assert(VAR_15 >= -256 && VAR_15<256);

        assert(VAR_17 >=0 && VAR_17<7);

        assert(VAR_5<4 || VAR_17==0);



        

        put_bits(&VAR_0->reorder_pb[VAR_5],

            multistage_vlc[1 + VAR_17][1],

            multistage_vlc[1 + VAR_17][0]);

        put_bits(&VAR_0->reorder_pb[VAR_5], mean_vlc[VAR_15][1],

            mean_vlc[VAR_15][0]);



        for (VAR_12 = 0; VAR_12 < VAR_17; VAR_12++){

            assert(VAR_18[VAR_12]>=0 && VAR_18[VAR_12]<16);

            put_bits(&VAR_0->reorder_pb[VAR_5], 4, VAR_18[VAR_12]);

        }



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

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

                VAR_3[VAR_11 + VAR_10*VAR_4]= VAR_1[VAR_11 + VAR_10*VAR_4] - block[VAR_17][VAR_11 + VAR_20*VAR_10] + VAR_15;

            }

        }

    }



    return VAR_16;

}

static int FUNC_0(SVQ1Context *VAR_0, FUNC_2 *VAR_1, FUNC_2 *VAR_2, FUNC_2 *VAR_3, int VAR_4, int VAR_5, int VAR_6, int VAR_7, int VAR_8){ int VAR_9, VAR_10, VAR_11, VAR_12, VAR_13, VAR_14, VAR_15, VAR_16, VAR_17; int VAR_18[6]; int VAR_19[7]= {0, 0, 0, 0, 0, 0}; int VAR_20= 2<<((VAR_5+2)>>1); int VAR_21= 2<<((VAR_5+1)>>1); int VAR_22=VAR_20*VAR_21; int16_t block[7][256]; const int8_t *VAR_23, *codebook; const FUNC_1 (*mean_vlc)[2]; const FUNC_2 (*multistage_vlc)[2]; VAR_16=0; if(VAR_8){ VAR_23= svq1_intra_codebook_sum[VAR_5]; codebook= svq1_intra_codebooks[VAR_5]; mean_vlc= svq1_intra_mean_vlc; multistage_vlc= svq1_intra_multistage_vlc[VAR_5]; for(VAR_10=0; VAR_10<VAR_21; VAR_10++){ for(VAR_11=0; VAR_11<VAR_20; VAR_11++){ int VAR_25= VAR_1[VAR_11 + VAR_10*VAR_4]; block[0][VAR_11 + VAR_20*VAR_10]= VAR_25; VAR_16 += VAR_25*VAR_25; VAR_19[0] += VAR_25; } } }else{ VAR_23= svq1_inter_codebook_sum[VAR_5]; codebook= svq1_inter_codebooks[VAR_5]; mean_vlc= svq1_inter_mean_vlc + 256; multistage_vlc= svq1_inter_multistage_vlc[VAR_5]; for(VAR_10=0; VAR_10<VAR_21; VAR_10++){ for(VAR_11=0; VAR_11<VAR_20; VAR_11++){ int VAR_25= VAR_1[VAR_11 + VAR_10*VAR_4] - VAR_2[VAR_11 + VAR_10*VAR_4]; block[0][VAR_11 + VAR_20*VAR_10]= VAR_25; VAR_16 += VAR_25*VAR_25; VAR_19[0] += VAR_25; } } } VAR_17=0; VAR_16 -= ((VAR_19[0]*VAR_19[0])>>(VAR_5+3)); VAR_15= (VAR_19[0] + (VAR_22>>1)) >> (VAR_5+3); if(VAR_5<4){ for(VAR_9=1; VAR_9<7; VAR_9++){ int VAR_25= INT_MAX; int VAR_26=-999, VAR_27=-999; const int VAR_28= VAR_9-1; const int8_t *VAR_29; for(VAR_12=0; VAR_12<16; VAR_12++){ int VAR_30= VAR_23[VAR_28*16 + VAR_12]; int VAR_31, VAR_32, VAR_33, VAR_35; VAR_29 = codebook + VAR_28*VAR_22*16 + VAR_12*VAR_22; VAR_31 = VAR_0->dsp.ssd_int8_vs_int16(VAR_29, block[VAR_28], VAR_22); VAR_32= VAR_19[VAR_28] - VAR_30; VAR_33= (VAR_32 + (VAR_22>>1)) >> (VAR_5+3); assert(VAR_33 >-300 && VAR_33<300); if(VAR_8) VAR_33= av_clip(VAR_33, 0, 255); else      VAR_33= av_clip(VAR_33, -256, 255); VAR_35= VAR_31 - ((VAR_32*(int64_t)VAR_32)>>(VAR_5+3)); if(VAR_35 < VAR_25){ VAR_25= VAR_35; VAR_18[VAR_28]= VAR_12; VAR_26= VAR_30; VAR_27= VAR_33; } } assert(VAR_27 != -999); VAR_29= codebook + VAR_28*VAR_22*16 + VAR_18[VAR_28]*VAR_22; for(VAR_13=0; VAR_13<VAR_22; VAR_13++){ block[VAR_28+1][VAR_13] = block[VAR_28][VAR_13] - VAR_29[VAR_13]; } VAR_19[VAR_28+1]= VAR_19[VAR_28] - VAR_26; VAR_25 +=
VAR_7*(+ 1 + 4*VAR_9
+ multistage_vlc[1+VAR_9][1]
+ mean_vlc[VAR_27][1]); if(VAR_25 < VAR_16){ VAR_16= VAR_25; VAR_17= VAR_9; VAR_15= VAR_27; } } } VAR_14=0; if(VAR_16 > VAR_6 && VAR_5){ int VAR_35=0; int VAR_35= (VAR_5&1) ? VAR_4*VAR_21/2 : VAR_20/2; PutBitContext backup[6]; for(VAR_12=VAR_5-1; VAR_12>=0; VAR_12--){ backup[VAR_12]= VAR_0->reorder_pb[VAR_12]; } VAR_35 += FUNC_0(VAR_0, VAR_1         , VAR_2         , VAR_3         , VAR_4, VAR_5-1, VAR_6>>1, VAR_7, VAR_8); VAR_35 += FUNC_0(VAR_0, VAR_1 + VAR_35, VAR_2 + VAR_35, VAR_3 + VAR_35, VAR_4, VAR_5-1, VAR_6>>1, VAR_7, VAR_8); VAR_35 += VAR_7; if(VAR_35 < VAR_16){ VAR_16= VAR_35; VAR_14=1; }else{ for(VAR_12=VAR_5-1; VAR_12>=0; VAR_12--){ VAR_0->reorder_pb[VAR_12]= backup[VAR_12]; } } } if (VAR_5 > 0)
put_bits(&VAR_0->reorder_pb[VAR_5], 1, VAR_14); if(!VAR_14){ assert((VAR_15 >= 0 && VAR_15<256) || !VAR_8); assert(VAR_15 >= -256 && VAR_15<256); assert(VAR_17 >=0 && VAR_17<7); assert(VAR_5<4 || VAR_17==0); put_bits(&VAR_0->reorder_pb[VAR_5],
multistage_vlc[1 + VAR_17][1],
multistage_vlc[1 + VAR_17][0]); put_bits(&VAR_0->reorder_pb[VAR_5], mean_vlc[VAR_15][1],
mean_vlc[VAR_15][0]); for (VAR_12 = 0; VAR_12 < VAR_17; VAR_12++){ assert(VAR_18[VAR_12]>=0 && VAR_18[VAR_12]<16); put_bits(&VAR_0->reorder_pb[VAR_5], 4, VAR_18[VAR_12]); } for(VAR_10=0; VAR_10<VAR_21; VAR_10++){ for(VAR_11=0; VAR_11<VAR_20; VAR_11++){ VAR_3[VAR_11 + VAR_10*VAR_4]= VAR_1[VAR_11 + VAR_10*VAR_4] - block[VAR_17][VAR_11 + VAR_20*VAR_10] + VAR_15; } } } return VAR_16; }