static int encode_thread(AVCodecContext *c, void *arg){

    MpegEncContext *s= *(void**)arg;

    int mb_x, mb_y, pdif = 0;

    int chr_h= 16>>s->chroma_y_shift;

    int i, j;

    MpegEncContext best_s, backup_s;

    uint8_t bit_buf[2][MAX_MB_BYTES];

    uint8_t bit_buf2[2][MAX_MB_BYTES];

    uint8_t bit_buf_tex[2][MAX_MB_BYTES];

    PutBitContext pb[2], pb2[2], tex_pb[2];

//printf("%d->%d\n", s->resync_mb_y, s->end_mb_y);

    ff_check_alignment();

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

        init_put_bits(&pb    [i], bit_buf    [i], MAX_MB_BYTES);

        init_put_bits(&pb2   [i], bit_buf2   [i], MAX_MB_BYTES);

        init_put_bits(&tex_pb[i], bit_buf_tex[i], MAX_MB_BYTES);

    }

    s->last_bits= put_bits_count(&s->pb);

    s->mv_bits=0;

    s->misc_bits=0;

    s->i_tex_bits=0;

    s->p_tex_bits=0;

    s->i_count=0;

    s->f_count=0;

    s->b_count=0;

    s->skip_count=0;

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

        /* init last dc values */

        /* note: quant matrix value (8) is implied here */

        s->last_dc[i] = 128 << s->intra_dc_precision;

        s->current_picture.error[i] = 0;

    }

    s->mb_skip_run = 0;

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

    s->last_mv_dir = 0;

    switch(s->codec_id){

    case CODEC_ID_H263:

    case CODEC_ID_H263P:

    case CODEC_ID_FLV1:

        if (CONFIG_H263_ENCODER || CONFIG_FLV_ENCODER)

            s->gob_index = ff_h263_get_gob_height(s);

        break;

    case CODEC_ID_MPEG4:

        if(CONFIG_MPEG4_ENCODER && s->partitioned_frame)

            ff_mpeg4_init_partitions(s);

        break;

    }

    s->resync_mb_x=0;

    s->resync_mb_y=0;

    s->first_slice_line = 1;

    s->ptr_lastgob = s->pb.buf;

    for(mb_y= s->start_mb_y; mb_y < s->end_mb_y; mb_y++) {

//    printf("row %d at %X\n", s->mb_y, (int)s);

        s->mb_x=0;

        s->mb_y= mb_y;

        ff_set_qscale(s, s->qscale);

        ff_init_block_index(s);

        for(mb_x=0; mb_x < s->mb_width; mb_x++) {

            int xy= mb_y*s->mb_stride + mb_x; // removed const, H261 needs to adjust this

            int mb_type= s->mb_type[xy];

//            int d;

            int dmin= INT_MAX;

            int dir;

            if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < MAX_MB_BYTES){

                av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");

                return -1;

            }

            if(s->data_partitioning){

                if(   s->pb2   .buf_end - s->pb2   .buf - (put_bits_count(&s->    pb2)>>3) < MAX_MB_BYTES

                   || s->tex_pb.buf_end - s->tex_pb.buf - (put_bits_count(&s->tex_pb )>>3) < MAX_MB_BYTES){

                    av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");

                    return -1;

                }

            }

            s->mb_x = mb_x;

            s->mb_y = mb_y;  // moved into loop, can get changed by H.261

            ff_update_block_index(s);

            if(CONFIG_H261_ENCODER && s->codec_id == CODEC_ID_H261){

                ff_h261_reorder_mb_index(s);

                xy= s->mb_y*s->mb_stride + s->mb_x;

                mb_type= s->mb_type[xy];

            }

            /* write gob / video packet header  */

            if(s->rtp_mode){

                int current_packet_size, is_gob_start;

                current_packet_size= ((put_bits_count(&s->pb)+7)>>3) - (s->ptr_lastgob - s->pb.buf);

                is_gob_start= s->avctx->rtp_payload_size && current_packet_size >= s->avctx->rtp_payload_size && mb_y + mb_x>0;

                if(s->start_mb_y == mb_y && mb_y > 0 && mb_x==0) is_gob_start=1;

                switch(s->codec_id){

                case CODEC_ID_H263:

                case CODEC_ID_H263P:

                    if(!s->h263_slice_structured)

                        if(s->mb_x || s->mb_y%s->gob_index) is_gob_start=0;

                    break;

                case CODEC_ID_MPEG2VIDEO:

                    if(s->mb_x==0 && s->mb_y!=0) is_gob_start=1;

                case CODEC_ID_MPEG1VIDEO:

                    if(s->mb_skip_run) is_gob_start=0;

                    break;

                }

                if(is_gob_start){

                    if(s->start_mb_y != mb_y || mb_x!=0){

                        write_slice_end(s);

                        if(CONFIG_MPEG4_ENCODER && s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame){

                            ff_mpeg4_init_partitions(s);

                        }

                    }

                    assert((put_bits_count(&s->pb)&7) == 0);

                    current_packet_size= put_bits_ptr(&s->pb) - s->ptr_lastgob;

                    if(s->avctx->error_rate && s->resync_mb_x + s->resync_mb_y > 0){

                        int r= put_bits_count(&s->pb)/8 + s->picture_number + 16 + s->mb_x + s->mb_y;

                        int d= 100 / s->avctx->error_rate;

                        if(r % d == 0){

                            current_packet_size=0;

#ifndef ALT_BITSTREAM_WRITER

                            s->pb.buf_ptr= s->ptr_lastgob;

#endif

                            assert(put_bits_ptr(&s->pb) == s->ptr_lastgob);

                        }

                    }

                    if (s->avctx->rtp_callback){

                        int number_mb = (mb_y - s->resync_mb_y)*s->mb_width + mb_x - s->resync_mb_x;

                        s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, current_packet_size, number_mb);

                    }

                    switch(s->codec_id){

                    case CODEC_ID_MPEG4:

                        if (CONFIG_MPEG4_ENCODER) {

                            ff_mpeg4_encode_video_packet_header(s);

                            ff_mpeg4_clean_buffers(s);

                        }

                    break;

                    case CODEC_ID_MPEG1VIDEO:

                    case CODEC_ID_MPEG2VIDEO:

                        if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) {

                            ff_mpeg1_encode_slice_header(s);

                            ff_mpeg1_clean_buffers(s);

                        }

                    break;

                    case CODEC_ID_H263:

                    case CODEC_ID_H263P:

                        if (CONFIG_H263_ENCODER)

                            h263_encode_gob_header(s, mb_y);

                    break;

                    }

                    if(s->flags&CODEC_FLAG_PASS1){

                        int bits= put_bits_count(&s->pb);

                        s->misc_bits+= bits - s->last_bits;

                        s->last_bits= bits;

                    }

                    s->ptr_lastgob += current_packet_size;

                    s->first_slice_line=1;

                    s->resync_mb_x=mb_x;

                    s->resync_mb_y=mb_y;

                }

            }

            if(  (s->resync_mb_x   == s->mb_x)

               && s->resync_mb_y+1 == s->mb_y){

                s->first_slice_line=0;

            }

            s->mb_skipped=0;

            s->dquant=0; //only for QP_RD

            if(mb_type & (mb_type-1) || (s->flags & CODEC_FLAG_QP_RD)){ // more than 1 MB type possible or CODEC_FLAG_QP_RD

                int next_block=0;

                int pb_bits_count, pb2_bits_count, tex_pb_bits_count;

                copy_context_before_encode(&backup_s, s, -1);

                backup_s.pb= s->pb;

                best_s.data_partitioning= s->data_partitioning;

                best_s.partitioned_frame= s->partitioned_frame;

                if(s->data_partitioning){

                    backup_s.pb2= s->pb2;

                    backup_s.tex_pb= s->tex_pb;

                }

                if(mb_type&CANDIDATE_MB_TYPE_INTER){

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_16X16;

                    s->mb_intra= 0;

                    s->mv[0][0][0] = s->p_mv_table[xy][0];

                    s->mv[0][0][1] = s->p_mv_table[xy][1];

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER, pb, pb2, tex_pb,

                                 &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]);

                }

                if(mb_type&CANDIDATE_MB_TYPE_INTER_I){

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_FIELD;

                    s->mb_intra= 0;

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

                        j= s->field_select[0][i] = s->p_field_select_table[i][xy];

                        s->mv[0][i][0] = s->p_field_mv_table[i][j][xy][0];

                        s->mv[0][i][1] = s->p_field_mv_table[i][j][xy][1];

                    }

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER_I, pb, pb2, tex_pb,

                                 &dmin, &next_block, 0, 0);

                }

                if(mb_type&CANDIDATE_MB_TYPE_SKIPPED){

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_16X16;

                    s->mb_intra= 0;

                    s->mv[0][0][0] = 0;

                    s->mv[0][0][1] = 0;

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_SKIPPED, pb, pb2, tex_pb,

                                 &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]);

                }

                if(mb_type&CANDIDATE_MB_TYPE_INTER4V){

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_8X8;

                    s->mb_intra= 0;

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

                        s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0];

                        s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1];

                    }

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER4V, pb, pb2, tex_pb,

                                 &dmin, &next_block, 0, 0);

                }

                if(mb_type&CANDIDATE_MB_TYPE_FORWARD){

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_16X16;

                    s->mb_intra= 0;

                    s->mv[0][0][0] = s->b_forw_mv_table[xy][0];

                    s->mv[0][0][1] = s->b_forw_mv_table[xy][1];

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_FORWARD, pb, pb2, tex_pb,

                                 &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]);

                }

                if(mb_type&CANDIDATE_MB_TYPE_BACKWARD){

                    s->mv_dir = MV_DIR_BACKWARD;

                    s->mv_type = MV_TYPE_16X16;

                    s->mb_intra= 0;

                    s->mv[1][0][0] = s->b_back_mv_table[xy][0];

                    s->mv[1][0][1] = s->b_back_mv_table[xy][1];

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BACKWARD, pb, pb2, tex_pb,

                                 &dmin, &next_block, s->mv[1][0][0], s->mv[1][0][1]);

                }

                if(mb_type&CANDIDATE_MB_TYPE_BIDIR){

                    s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;

                    s->mv_type = MV_TYPE_16X16;

                    s->mb_intra= 0;

                    s->mv[0][0][0] = s->b_bidir_forw_mv_table[xy][0];

                    s->mv[0][0][1] = s->b_bidir_forw_mv_table[xy][1];

                    s->mv[1][0][0] = s->b_bidir_back_mv_table[xy][0];

                    s->mv[1][0][1] = s->b_bidir_back_mv_table[xy][1];

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BIDIR, pb, pb2, tex_pb,

                                 &dmin, &next_block, 0, 0);

                }

                if(mb_type&CANDIDATE_MB_TYPE_FORWARD_I){

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_FIELD;

                    s->mb_intra= 0;

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

                        j= s->field_select[0][i] = s->b_field_select_table[0][i][xy];

                        s->mv[0][i][0] = s->b_field_mv_table[0][i][j][xy][0];

                        s->mv[0][i][1] = s->b_field_mv_table[0][i][j][xy][1];

                    }

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_FORWARD_I, pb, pb2, tex_pb,

                                 &dmin, &next_block, 0, 0);

                }

                if(mb_type&CANDIDATE_MB_TYPE_BACKWARD_I){

                    s->mv_dir = MV_DIR_BACKWARD;

                    s->mv_type = MV_TYPE_FIELD;

                    s->mb_intra= 0;

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

                        j= s->field_select[1][i] = s->b_field_select_table[1][i][xy];

                        s->mv[1][i][0] = s->b_field_mv_table[1][i][j][xy][0];

                        s->mv[1][i][1] = s->b_field_mv_table[1][i][j][xy][1];

                    }

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BACKWARD_I, pb, pb2, tex_pb,

                                 &dmin, &next_block, 0, 0);

                }

                if(mb_type&CANDIDATE_MB_TYPE_BIDIR_I){

                    s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;

                    s->mv_type = MV_TYPE_FIELD;

                    s->mb_intra= 0;

                    for(dir=0; dir<2; dir++){

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

                            j= s->field_select[dir][i] = s->b_field_select_table[dir][i][xy];

                            s->mv[dir][i][0] = s->b_field_mv_table[dir][i][j][xy][0];

                            s->mv[dir][i][1] = s->b_field_mv_table[dir][i][j][xy][1];

                        }

                    }

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BIDIR_I, pb, pb2, tex_pb,

                                 &dmin, &next_block, 0, 0);

                }

                if(mb_type&CANDIDATE_MB_TYPE_INTRA){

                    s->mv_dir = 0;

                    s->mv_type = MV_TYPE_16X16;

                    s->mb_intra= 1;

                    s->mv[0][0][0] = 0;

                    s->mv[0][0][1] = 0;

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTRA, pb, pb2, tex_pb,

                                 &dmin, &next_block, 0, 0);

                    if(s->h263_pred || s->h263_aic){

                        if(best_s.mb_intra)

                            s->mbintra_table[mb_x + mb_y*s->mb_stride]=1;

                        else

                            ff_clean_intra_table_entries(s); //old mode?

                    }

                }

                if((s->flags & CODEC_FLAG_QP_RD) && dmin < INT_MAX){

                    if(best_s.mv_type==MV_TYPE_16X16){ //FIXME move 4mv after QPRD

                        const int last_qp= backup_s.qscale;

                        int qpi, qp, dc[6];

                        DCTELEM ac[6][16];

                        const int mvdir= (best_s.mv_dir&MV_DIR_BACKWARD) ? 1 : 0;

                        static const int dquant_tab[4]={-1,1,-2,2};

                        assert(backup_s.dquant == 0);

                        //FIXME intra

                        s->mv_dir= best_s.mv_dir;

                        s->mv_type = MV_TYPE_16X16;

                        s->mb_intra= best_s.mb_intra;

                        s->mv[0][0][0] = best_s.mv[0][0][0];

                        s->mv[0][0][1] = best_s.mv[0][0][1];

                        s->mv[1][0][0] = best_s.mv[1][0][0];

                        s->mv[1][0][1] = best_s.mv[1][0][1];

                        qpi = s->pict_type == FF_B_TYPE ? 2 : 0;

                        for(; qpi<4; qpi++){

                            int dquant= dquant_tab[qpi];

                            qp= last_qp + dquant;

                            if(qp < s->avctx->qmin || qp > s->avctx->qmax)

                                continue;

                            backup_s.dquant= dquant;

                            if(s->mb_intra && s->dc_val[0]){

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

                                    dc[i]= s->dc_val[0][ s->block_index[i] ];

                                    memcpy(ac[i], s->ac_val[0][s->block_index[i]], sizeof(DCTELEM)*16);

                                }

                            }

                            encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER /* wrong but unused */, pb, pb2, tex_pb,

                                         &dmin, &next_block, s->mv[mvdir][0][0], s->mv[mvdir][0][1]);

                            if(best_s.qscale != qp){

                                if(s->mb_intra && s->dc_val[0]){

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

                                        s->dc_val[0][ s->block_index[i] ]= dc[i];

                                        memcpy(s->ac_val[0][s->block_index[i]], ac[i], sizeof(DCTELEM)*16);

                                    }

                                }

                            }

                        }

                    }

                }

                if(CONFIG_MPEG4_ENCODER && mb_type&CANDIDATE_MB_TYPE_DIRECT){

                    int mx= s->b_direct_mv_table[xy][0];

                    int my= s->b_direct_mv_table[xy][1];

                    backup_s.dquant = 0;

                    s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT;

                    s->mb_intra= 0;

                    ff_mpeg4_set_direct_mv(s, mx, my);

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb,

                                 &dmin, &next_block, mx, my);

                }

                if(CONFIG_MPEG4_ENCODER && mb_type&CANDIDATE_MB_TYPE_DIRECT0){

                    backup_s.dquant = 0;

                    s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT;

                    s->mb_intra= 0;

                    ff_mpeg4_set_direct_mv(s, 0, 0);

                    encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb,

                                 &dmin, &next_block, 0, 0);

                }

                if(!best_s.mb_intra && s->flags2&CODEC_FLAG2_SKIP_RD){

                    int coded=0;

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

                        coded |= s->block_last_index[i];

                    if(coded){

                        int mx,my;

                        memcpy(s->mv, best_s.mv, sizeof(s->mv));

                        if(CONFIG_MPEG4_ENCODER && best_s.mv_dir & MV_DIRECT){

                            mx=my=0; //FIXME find the one we actually used

                            ff_mpeg4_set_direct_mv(s, mx, my);

                        }else if(best_s.mv_dir&MV_DIR_BACKWARD){

                            mx= s->mv[1][0][0];

                            my= s->mv[1][0][1];

                        }else{

                            mx= s->mv[0][0][0];

                            my= s->mv[0][0][1];

                        }

                        s->mv_dir= best_s.mv_dir;

                        s->mv_type = best_s.mv_type;

                        s->mb_intra= 0;

/*                        s->mv[0][0][0] = best_s.mv[0][0][0];

                        s->mv[0][0][1] = best_s.mv[0][0][1];

                        s->mv[1][0][0] = best_s.mv[1][0][0];

                        s->mv[1][0][1] = best_s.mv[1][0][1];*/

                        backup_s.dquant= 0;

                        s->skipdct=1;

                        encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER /* wrong but unused */, pb, pb2, tex_pb,

                                        &dmin, &next_block, mx, my);

                        s->skipdct=0;

                    }

                }

                s->current_picture.qscale_table[xy]= best_s.qscale;

                copy_context_after_encode(s, &best_s, -1);

                pb_bits_count= put_bits_count(&s->pb);

                flush_put_bits(&s->pb);

                ff_copy_bits(&backup_s.pb, bit_buf[next_block^1], pb_bits_count);

                s->pb= backup_s.pb;

                if(s->data_partitioning){

                    pb2_bits_count= put_bits_count(&s->pb2);

                    flush_put_bits(&s->pb2);

                    ff_copy_bits(&backup_s.pb2, bit_buf2[next_block^1], pb2_bits_count);

                    s->pb2= backup_s.pb2;

                    tex_pb_bits_count= put_bits_count(&s->tex_pb);

                    flush_put_bits(&s->tex_pb);

                    ff_copy_bits(&backup_s.tex_pb, bit_buf_tex[next_block^1], tex_pb_bits_count);

                    s->tex_pb= backup_s.tex_pb;

                }

                s->last_bits= put_bits_count(&s->pb);

                if (CONFIG_ANY_H263_ENCODER &&

                    s->out_format == FMT_H263 && s->pict_type!=FF_B_TYPE)

                    ff_h263_update_motion_val(s);

                if(next_block==0){ //FIXME 16 vs linesize16

                    s->dsp.put_pixels_tab[0][0](s->dest[0], s->rd_scratchpad                     , s->linesize  ,16);

                    s->dsp.put_pixels_tab[1][0](s->dest[1], s->rd_scratchpad + 16*s->linesize    , s->uvlinesize, 8);

                    s->dsp.put_pixels_tab[1][0](s->dest[2], s->rd_scratchpad + 16*s->linesize + 8, s->uvlinesize, 8);

                }

                if(s->avctx->mb_decision == FF_MB_DECISION_BITS)

                    MPV_decode_mb(s, s->block);

            } else {

                int motion_x = 0, motion_y = 0;

                s->mv_type=MV_TYPE_16X16;

                // only one MB-Type possible

                switch(mb_type){

                case CANDIDATE_MB_TYPE_INTRA:

                    s->mv_dir = 0;

                    s->mb_intra= 1;

                    motion_x= s->mv[0][0][0] = 0;

                    motion_y= s->mv[0][0][1] = 0;

                    break;

                case CANDIDATE_MB_TYPE_INTER:

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mb_intra= 0;

                    motion_x= s->mv[0][0][0] = s->p_mv_table[xy][0];

                    motion_y= s->mv[0][0][1] = s->p_mv_table[xy][1];

                    break;

                case CANDIDATE_MB_TYPE_INTER_I:

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_FIELD;

                    s->mb_intra= 0;

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

                        j= s->field_select[0][i] = s->p_field_select_table[i][xy];

                        s->mv[0][i][0] = s->p_field_mv_table[i][j][xy][0];

                        s->mv[0][i][1] = s->p_field_mv_table[i][j][xy][1];

                    }

                    break;

                case CANDIDATE_MB_TYPE_INTER4V:

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_8X8;

                    s->mb_intra= 0;

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

                        s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0];

                        s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1];

                    }

                    break;

                case CANDIDATE_MB_TYPE_DIRECT:

                    if (CONFIG_MPEG4_ENCODER) {

                        s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD|MV_DIRECT;

                        s->mb_intra= 0;

                        motion_x=s->b_direct_mv_table[xy][0];

                        motion_y=s->b_direct_mv_table[xy][1];

                        ff_mpeg4_set_direct_mv(s, motion_x, motion_y);

                    }

                    break;

                case CANDIDATE_MB_TYPE_DIRECT0:

                    if (CONFIG_MPEG4_ENCODER) {

                        s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD|MV_DIRECT;

                        s->mb_intra= 0;

                        ff_mpeg4_set_direct_mv(s, 0, 0);

                    }

                    break;

                case CANDIDATE_MB_TYPE_BIDIR:

                    s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;

                    s->mb_intra= 0;

                    s->mv[0][0][0] = s->b_bidir_forw_mv_table[xy][0];

                    s->mv[0][0][1] = s->b_bidir_forw_mv_table[xy][1];

                    s->mv[1][0][0] = s->b_bidir_back_mv_table[xy][0];

                    s->mv[1][0][1] = s->b_bidir_back_mv_table[xy][1];

                    break;

                case CANDIDATE_MB_TYPE_BACKWARD:

                    s->mv_dir = MV_DIR_BACKWARD;

                    s->mb_intra= 0;

                    motion_x= s->mv[1][0][0] = s->b_back_mv_table[xy][0];

                    motion_y= s->mv[1][0][1] = s->b_back_mv_table[xy][1];

                    break;

                case CANDIDATE_MB_TYPE_FORWARD:

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mb_intra= 0;

                    motion_x= s->mv[0][0][0] = s->b_forw_mv_table[xy][0];

                    motion_y= s->mv[0][0][1] = s->b_forw_mv_table[xy][1];

//                    printf(" %d %d ", motion_x, motion_y);

                    break;

                case CANDIDATE_MB_TYPE_FORWARD_I:

                    s->mv_dir = MV_DIR_FORWARD;

                    s->mv_type = MV_TYPE_FIELD;

                    s->mb_intra= 0;

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

                        j= s->field_select[0][i] = s->b_field_select_table[0][i][xy];

                        s->mv[0][i][0] = s->b_field_mv_table[0][i][j][xy][0];

                        s->mv[0][i][1] = s->b_field_mv_table[0][i][j][xy][1];

                    }

                    break;

                case CANDIDATE_MB_TYPE_BACKWARD_I:

                    s->mv_dir = MV_DIR_BACKWARD;

                    s->mv_type = MV_TYPE_FIELD;

                    s->mb_intra= 0;

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

                        j= s->field_select[1][i] = s->b_field_select_table[1][i][xy];

                        s->mv[1][i][0] = s->b_field_mv_table[1][i][j][xy][0];

                        s->mv[1][i][1] = s->b_field_mv_table[1][i][j][xy][1];

                    }

                    break;

                case CANDIDATE_MB_TYPE_BIDIR_I:

                    s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD;

                    s->mv_type = MV_TYPE_FIELD;

                    s->mb_intra= 0;

                    for(dir=0; dir<2; dir++){

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

                            j= s->field_select[dir][i] = s->b_field_select_table[dir][i][xy];

                            s->mv[dir][i][0] = s->b_field_mv_table[dir][i][j][xy][0];

                            s->mv[dir][i][1] = s->b_field_mv_table[dir][i][j][xy][1];

                        }

                    }

                    break;

                default:

                    av_log(s->avctx, AV_LOG_ERROR, "illegal MB type\n");

                }

                encode_mb(s, motion_x, motion_y);

                // RAL: Update last macroblock type

                s->last_mv_dir = s->mv_dir;

                if (CONFIG_ANY_H263_ENCODER &&

                    s->out_format == FMT_H263 && s->pict_type!=FF_B_TYPE)

                    ff_h263_update_motion_val(s);

                MPV_decode_mb(s, s->block);

            }

            /* clean the MV table in IPS frames for direct mode in B frames */

            if(s->mb_intra /* && I,P,S_TYPE */){

                s->p_mv_table[xy][0]=0;

                s->p_mv_table[xy][1]=0;

            }

            if(s->flags&CODEC_FLAG_PSNR){

                int w= 16;

                int h= 16;

                if(s->mb_x*16 + 16 > s->width ) w= s->width - s->mb_x*16;

                if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16;

                s->current_picture.error[0] += sse(

                    s, s->new_picture.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16,

                    s->dest[0], w, h, s->linesize);

                s->current_picture.error[1] += sse(

                    s, s->new_picture.data[1] + s->mb_x*8  + s->mb_y*s->uvlinesize*chr_h,

                    s->dest[1], w>>1, h>>s->chroma_y_shift, s->uvlinesize);

                s->current_picture.error[2] += sse(

                    s, s->new_picture.data[2] + s->mb_x*8  + s->mb_y*s->uvlinesize*chr_h,

                    s->dest[2], w>>1, h>>s->chroma_y_shift, s->uvlinesize);

            }

            if(s->loop_filter){

                if(CONFIG_ANY_H263_ENCODER && s->out_format == FMT_H263)

                    ff_h263_loop_filter(s);

            }

//printf("MB %d %d bits\n", s->mb_x+s->mb_y*s->mb_stride, put_bits_count(&s->pb));

        }

    }

    //not beautiful here but we must write it before flushing so it has to be here

    if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type == FF_I_TYPE)

        msmpeg4_encode_ext_header(s);

    write_slice_end(s);

    /* Send the last GOB if RTP */

    if (s->avctx->rtp_callback) {

        int number_mb = (mb_y - s->resync_mb_y)*s->mb_width - s->resync_mb_x;

        pdif = put_bits_ptr(&s->pb) - s->ptr_lastgob;

        /* Call the RTP callback to send the last GOB */

        emms_c();

        s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, pdif, number_mb);

    }

    return 0;

}


static void new_audio_stream(AVFormatContext *oc, int file_idx)

{

    AVStream *st;

    OutputStream *ost;

    AVCodec *codec= NULL;

    AVCodecContext *audio_enc;

    enum CodecID codec_id = CODEC_ID_NONE;

    if(!audio_stream_copy){

        if (audio_codec_name) {

            codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1,

                                         avcodec_opts[AVMEDIA_TYPE_AUDIO]->strict_std_compliance);

            codec = avcodec_find_encoder_by_name(audio_codec_name);

        } else {

            codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO);

            codec = avcodec_find_encoder(codec_id);

        }

    }

    ost = new_output_stream(oc, file_idx, codec);

    st  = ost->st;

    ost->bitstream_filters = audio_bitstream_filters;

    audio_bitstream_filters= NULL;

    st->codec->thread_count= thread_count;

    audio_enc = st->codec;

    audio_enc->codec_type = AVMEDIA_TYPE_AUDIO;

    if(audio_codec_tag)

        audio_enc->codec_tag= audio_codec_tag;

    if (oc->oformat->flags & AVFMT_GLOBALHEADER) {

        audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;

    }

    if (audio_stream_copy) {

        st->stream_copy = 1;

    } else {

        audio_enc->codec_id = codec_id;

        set_context_opts(audio_enc, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);

        if (audio_qscale > QSCALE_NONE) {

            audio_enc->flags |= CODEC_FLAG_QSCALE;

            audio_enc->global_quality = FF_QP2LAMBDA * audio_qscale;

        }

        if (audio_channels)

            audio_enc->channels = audio_channels;

        if (audio_sample_fmt != AV_SAMPLE_FMT_NONE)

            audio_enc->sample_fmt = audio_sample_fmt;

        if (audio_sample_rate)

            audio_enc->sample_rate = audio_sample_rate;

    }

    if (audio_language) {

        av_dict_set(&st->metadata, "language", audio_language, 0);

        av_freep(&audio_language);

    }

    /* reset some key parameters */

    audio_disable = 0;

    av_freep(&audio_codec_name);

    audio_stream_copy = 0;

}


static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,

                                 VirtQueueElement *elem)

{

    struct virtio_net_ctrl_mac mac_data;

    if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET || elem->out_num != 3 ||

        elem->out_sg[1].iov_len < sizeof(mac_data) ||

        elem->out_sg[2].iov_len < sizeof(mac_data))

        return VIRTIO_NET_ERR;

    n->mac_table.in_use = 0;

    memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);

    mac_data.entries = ldl_le_p(elem->out_sg[1].iov_base);

    if (sizeof(mac_data.entries) +

        (mac_data.entries * ETH_ALEN) > elem->out_sg[1].iov_len)

        return VIRTIO_NET_ERR;

    if (mac_data.entries <= MAC_TABLE_ENTRIES) {

        memcpy(n->mac_table.macs, elem->out_sg[1].iov_base + sizeof(mac_data),

               mac_data.entries * ETH_ALEN);

        n->mac_table.in_use += mac_data.entries;

    } else {

        n->promisc = 1;

        return VIRTIO_NET_OK;

    }

    mac_data.entries = ldl_le_p(elem->out_sg[2].iov_base);

    if (sizeof(mac_data.entries) +

        (mac_data.entries * ETH_ALEN) > elem->out_sg[2].iov_len)

        return VIRTIO_NET_ERR;

    if (mac_data.entries) {

        if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) {

            memcpy(n->mac_table.macs + (n->mac_table.in_use * ETH_ALEN),

                   elem->out_sg[2].iov_base + sizeof(mac_data),

                   mac_data.entries * ETH_ALEN);

            n->mac_table.in_use += mac_data.entries;

        } else

            n->allmulti = 1;

    }

    return VIRTIO_NET_OK;

}


static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,

                            void *data,

                            size_t len) {

    VncState *vs = (VncState *)transport;

    int ret;

 retry:

    ret = qemu_recv(vs->csock, data, len, 0);

    if (ret < 0) {

        if (errno == EINTR)

            goto retry;

        return -1;

    }

    return ret;

}


file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)

{

    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);

    if (!backend->size) {

        error_setg(errp, "can't create backend with size 0");

        return;

    }

    if (!fb->mem_path) {

        error_setg(errp, "mem-path property not set");

        return;

    }

#ifndef CONFIG_LINUX

    error_setg(errp, "-mem-path not supported on this host");

#else

    if (!memory_region_size(&backend->mr)) {

        backend->force_prealloc = mem_prealloc;

        memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),

                                 object_get_canonical_path(OBJECT(backend)),

                                 backend->size, fb->share,

                                 fb->mem_path, errp);

    }

#endif

}


sorecvoob(struct socket *so)

{

	struct tcpcb *tp = sototcpcb(so);

	DEBUG_CALL("sorecvoob");

	DEBUG_ARG("so = %p", so);

	/*

	 * We take a guess at how much urgent data has arrived.

	 * In most situations, when urgent data arrives, the next

	 * read() should get all the urgent data.  This guess will

	 * be wrong however if more data arrives just after the

	 * urgent data, or the read() doesn't return all the

	 * urgent data.

	 */

	soread(so);

	tp->snd_up = tp->snd_una + so->so_snd.sb_cc;

	tp->t_force = 1;

	tcp_output(tp);

	tp->t_force = 0;

}


static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)

{

    RTCState *s = opaque;

    int ret;

    if ((addr & 1) == 0) {

        return 0xff;

    } else {

        switch(s->cmos_index) {

        case RTC_SECONDS:

        case RTC_MINUTES:

        case RTC_HOURS:

        case RTC_DAY_OF_WEEK:

        case RTC_DAY_OF_MONTH:

        case RTC_MONTH:

        case RTC_YEAR:

            ret = s->cmos_data[s->cmos_index];

            break;

        case RTC_REG_A:

            ret = s->cmos_data[s->cmos_index];

            break;

        case RTC_REG_C:

            ret = s->cmos_data[s->cmos_index];

            qemu_irq_lower(s->irq);

#ifdef TARGET_I386

            if(s->irq_coalesced) {

                apic_reset_irq_delivered();

                qemu_irq_raise(s->irq);

                if (apic_get_irq_delivered())

                    s->irq_coalesced--;

                break;

            }

#endif

            s->cmos_data[RTC_REG_C] = 0x00;

            break;

        default:

            ret = s->cmos_data[s->cmos_index];

            break;

        }

#ifdef DEBUG_CMOS

        printf("cmos: read index=0x%02x val=0x%02x\n",

               s->cmos_index, ret);

#endif

        return ret;

    }

}


iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,

                        void *command_data, void *opaque)

{

    struct IscsiTask *iTask = opaque;

    struct scsi_task *task = command_data;

    iTask->status = status;

    iTask->do_retry = 0;

    iTask->task = task;

    if (status != SCSI_STATUS_GOOD) {

        if (iTask->retries++ < ISCSI_CMD_RETRIES) {

            if (status == SCSI_STATUS_CHECK_CONDITION

                && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {

                error_report("iSCSI CheckCondition: %s",

                             iscsi_get_error(iscsi));

                iTask->do_retry = 1;

                goto out;

            }

            /* status 0x28 is SCSI_TASK_SET_FULL. It was first introduced

             * in libiscsi 1.10.0. Hardcode this value here to avoid

             * the need to bump the libiscsi requirement to 1.10.0 */

            if (status == SCSI_STATUS_BUSY || status == 0x28) {

                unsigned retry_time =

                    exp_random(iscsi_retry_times[iTask->retries - 1]);

                error_report("iSCSI Busy/TaskSetFull (retry #%u in %u ms): %s",

                             iTask->retries, retry_time,

                             iscsi_get_error(iscsi));

                aio_timer_init(iTask->iscsilun->aio_context,

                               &iTask->retry_timer, QEMU_CLOCK_REALTIME,

                               SCALE_MS, iscsi_retry_timer_expired, iTask);

                timer_mod(&iTask->retry_timer,

                          qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time);

                iTask->do_retry = 1;

                return;

            }

        }

        error_report("iSCSI Failure: %s", iscsi_get_error(iscsi));

    } else {

        iTask->iscsilun->force_next_flush |= iTask->force_next_flush;

    }

out:

    if (iTask->co) {

        iTask->bh = aio_bh_new(iTask->iscsilun->aio_context,

                               iscsi_co_generic_bh_cb, iTask);

        qemu_bh_schedule(iTask->bh);

    } else {

        iTask->complete = 1;

    }

}


int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples,

                                              int *frame_size_ptr,

                                              AVPacket *avpkt)

{

    AVFrame frame = {0};

    int ret, got_frame = 0;

    if (avctx->get_buffer != avcodec_default_get_buffer) {

        av_log(avctx, AV_LOG_ERROR, "Custom get_buffer() for use with"

                                    "avcodec_decode_audio3() detected. Overriding with avcodec_default_get_buffer\n");

        av_log(avctx, AV_LOG_ERROR, "Please port your application to "

                                    "avcodec_decode_audio4()\n");

        avctx->get_buffer = avcodec_default_get_buffer;

    }

    ret = avcodec_decode_audio4(avctx, &frame, &got_frame, avpkt);

    if (ret >= 0 && got_frame) {

        int ch, plane_size;

        int planar    = av_sample_fmt_is_planar(avctx->sample_fmt);

        int data_size = av_samples_get_buffer_size(&plane_size, avctx->channels,

                                                   frame.nb_samples,

                                                   avctx->sample_fmt, 1);

        if (*frame_size_ptr < data_size) {

            av_log(avctx, AV_LOG_ERROR, "output buffer size is too small for "

                                        "the current frame (%d < %d)\n", *frame_size_ptr, data_size);

            return AVERROR(EINVAL);

        }

        memcpy(samples, frame.extended_data[0], plane_size);

        if (planar && avctx->channels > 1) {

            uint8_t *out = ((uint8_t *)samples) + plane_size;

            for (ch = 1; ch < avctx->channels; ch++) {

                memcpy(out, frame.extended_data[ch], plane_size);

                out += plane_size;

            }

        }

        *frame_size_ptr = data_size;

    } else {

        *frame_size_ptr = 0;

    }

    return ret;

}


static int ape_read_header(AVFormatContext * s)

{

    AVIOContext *pb = s->pb;

    APEContext *ape = s->priv_data;

    AVStream *st;

    uint32_t tag;

    int i;

    int total_blocks, final_size = 0;

    int64_t pts, file_size;

    /* Skip any leading junk such as id3v2 tags */

    ape->junklength = avio_tell(pb);

    tag = avio_rl32(pb);

    if (tag != MKTAG('M', 'A', 'C', ' '))

        return AVERROR_INVALIDDATA;

    ape->fileversion = avio_rl16(pb);

    if (ape->fileversion < APE_MIN_VERSION || ape->fileversion > APE_MAX_VERSION) {

        av_log(s, AV_LOG_ERROR, "Unsupported file version - %d.%02d\n",

               ape->fileversion / 1000, (ape->fileversion % 1000) / 10);

        return AVERROR_PATCHWELCOME;

    }

    if (ape->fileversion >= 3980) {

        ape->padding1             = avio_rl16(pb);

        ape->descriptorlength     = avio_rl32(pb);

        ape->headerlength         = avio_rl32(pb);

        ape->seektablelength      = avio_rl32(pb);

        ape->wavheaderlength      = avio_rl32(pb);

        ape->audiodatalength      = avio_rl32(pb);

        ape->audiodatalength_high = avio_rl32(pb);

        ape->wavtaillength        = avio_rl32(pb);

        avio_read(pb, ape->md5, 16);

        /* Skip any unknown bytes at the end of the descriptor.

           This is for future compatibility */

        if (ape->descriptorlength > 52)

            avio_skip(pb, ape->descriptorlength - 52);

        /* Read header data */

        ape->compressiontype      = avio_rl16(pb);

        ape->formatflags          = avio_rl16(pb);

        ape->blocksperframe       = avio_rl32(pb);

        ape->finalframeblocks     = avio_rl32(pb);

        ape->totalframes          = avio_rl32(pb);

        ape->bps                  = avio_rl16(pb);

        ape->channels             = avio_rl16(pb);

        ape->samplerate           = avio_rl32(pb);

    } else {

        ape->descriptorlength = 0;

        ape->headerlength = 32;

        ape->compressiontype      = avio_rl16(pb);

        ape->formatflags          = avio_rl16(pb);

        ape->channels             = avio_rl16(pb);

        ape->samplerate           = avio_rl32(pb);

        ape->wavheaderlength      = avio_rl32(pb);

        ape->wavtaillength        = avio_rl32(pb);

        ape->totalframes          = avio_rl32(pb);

        ape->finalframeblocks     = avio_rl32(pb);

        if (ape->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL) {

            avio_skip(pb, 4); /* Skip the peak level */

            ape->headerlength += 4;

        }

        if (ape->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS) {

            ape->seektablelength = avio_rl32(pb);

            ape->headerlength += 4;

            ape->seektablelength *= sizeof(int32_t);

        } else

            ape->seektablelength = ape->totalframes * sizeof(int32_t);

        if (ape->formatflags & MAC_FORMAT_FLAG_8_BIT)

            ape->bps = 8;

        else if (ape->formatflags & MAC_FORMAT_FLAG_24_BIT)

            ape->bps = 24;

        else

            ape->bps = 16;

        if (ape->fileversion >= 3950)

            ape->blocksperframe = 73728 * 4;

        else if (ape->fileversion >= 3900 || (ape->fileversion >= 3800  && ape->compressiontype >= 4000))

            ape->blocksperframe = 73728;

        else

            ape->blocksperframe = 9216;

        /* Skip any stored wav header */

        if (!(ape->formatflags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER))

            avio_skip(pb, ape->wavheaderlength);

    }

    if(!ape->totalframes){

        av_log(s, AV_LOG_ERROR, "No frames in the file!\n");

        return AVERROR(EINVAL);

    }

    if(ape->totalframes > UINT_MAX / sizeof(APEFrame)){

        av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n",

               ape->totalframes);

        return AVERROR_INVALIDDATA;

    }

    if (ape->seektablelength / sizeof(*ape->seektable) < ape->totalframes) {

        av_log(s, AV_LOG_ERROR,

               "Number of seek entries is less than number of frames: %zu vs. %"PRIu32"\n",

               ape->seektablelength / sizeof(*ape->seektable), ape->totalframes);

        return AVERROR_INVALIDDATA;

    }

    ape->frames       = av_malloc(ape->totalframes * sizeof(APEFrame));

    if(!ape->frames)

        return AVERROR(ENOMEM);

    ape->firstframe   = ape->junklength + ape->descriptorlength + ape->headerlength + ape->seektablelength + ape->wavheaderlength;

    if (ape->fileversion < 3810)

        ape->firstframe += ape->totalframes;

    ape->currentframe = 0;

    ape->totalsamples = ape->finalframeblocks;

    if (ape->totalframes > 1)

        ape->totalsamples += ape->blocksperframe * (ape->totalframes - 1);

    if (ape->seektablelength > 0) {

        ape->seektable = av_malloc(ape->seektablelength);

        if (!ape->seektable)

            return AVERROR(ENOMEM);

        for (i = 0; i < ape->seektablelength / sizeof(uint32_t) && !pb->eof_reached; i++)

            ape->seektable[i] = avio_rl32(pb);

        if (ape->fileversion < 3810) {

            ape->bittable = av_malloc(ape->totalframes);

            if (!ape->bittable)

                return AVERROR(ENOMEM);

            for (i = 0; i < ape->totalframes && !pb->eof_reached; i++)

                ape->bittable[i] = avio_r8(pb);

        }

    }

    ape->frames[0].pos     = ape->firstframe;

    ape->frames[0].nblocks = ape->blocksperframe;

    ape->frames[0].skip    = 0;

    for (i = 1; i < ape->totalframes; i++) {

        ape->frames[i].pos      = ape->seektable[i] + ape->junklength;

        ape->frames[i].nblocks  = ape->blocksperframe;

        ape->frames[i - 1].size = ape->frames[i].pos - ape->frames[i - 1].pos;

        ape->frames[i].skip     = (ape->frames[i].pos - ape->frames[0].pos) & 3;

    }

    ape->frames[ape->totalframes - 1].nblocks = ape->finalframeblocks;

    /* calculate final packet size from total file size, if available */

    file_size = avio_size(pb);

    if (file_size > 0) {

        final_size = file_size - ape->frames[ape->totalframes - 1].pos -

                     ape->wavtaillength;

        final_size -= final_size & 3;

    }

    if (file_size <= 0 || final_size <= 0)

        final_size = ape->finalframeblocks * 8;

    ape->frames[ape->totalframes - 1].size = final_size;

    for (i = 0; i < ape->totalframes; i++) {

        if(ape->frames[i].skip){

            ape->frames[i].pos  -= ape->frames[i].skip;

            ape->frames[i].size += ape->frames[i].skip;

        }

        ape->frames[i].size = (ape->frames[i].size + 3) & ~3;

    }

    if (ape->fileversion < 3810) {

        for (i = 0; i < ape->totalframes; i++) {

            if (i < ape->totalframes - 1 && ape->bittable[i + 1])

                ape->frames[i].size += 4;

            ape->frames[i].skip <<= 3;

            ape->frames[i].skip  += ape->bittable[i];

        }

    }

    ape_dumpinfo(s, ape);

    av_log(s, AV_LOG_DEBUG, "Decoding file - v%d.%02d, compression level %"PRIu16"\n",

           ape->fileversion / 1000, (ape->fileversion % 1000) / 10,

           ape->compressiontype);

    /* now we are ready: build format streams */

    st = avformat_new_stream(s, NULL);

    if (!st)

        return AVERROR(ENOMEM);

    total_blocks = (ape->totalframes == 0) ? 0 : ((ape->totalframes - 1) * ape->blocksperframe) + ape->finalframeblocks;

    st->codec->codec_type      = AVMEDIA_TYPE_AUDIO;

    st->codec->codec_id        = AV_CODEC_ID_APE;

    st->codec->codec_tag       = MKTAG('A', 'P', 'E', ' ');

    st->codec->channels        = ape->channels;

    st->codec->sample_rate     = ape->samplerate;

    st->codec->bits_per_coded_sample = ape->bps;

    st->nb_frames = ape->totalframes;

    st->start_time = 0;

    st->duration  = total_blocks;

    avpriv_set_pts_info(st, 64, 1, ape->samplerate);

    if (ff_alloc_extradata(st->codec, APE_EXTRADATA_SIZE))

        return AVERROR(ENOMEM);

    AV_WL16(st->codec->extradata + 0, ape->fileversion);

    AV_WL16(st->codec->extradata + 2, ape->compressiontype);

    AV_WL16(st->codec->extradata + 4, ape->formatflags);

    pts = 0;

    for (i = 0; i < ape->totalframes; i++) {

        ape->frames[i].pts = pts;

        av_add_index_entry(st, ape->frames[i].pos, ape->frames[i].pts, 0, 0, AVINDEX_KEYFRAME);

        pts += ape->blocksperframe;

    }

    /* try to read APE tags */

    if (pb->seekable) {

        ff_ape_parse_tag(s);

        avio_seek(pb, 0, SEEK_SET);

    }

    return 0;

}


int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,

                         int level)

{

    VDPAUHWContext *hwctx = avctx->hwaccel_context;

    VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;

    VdpVideoSurfaceQueryCapabilities *surface_query_caps;

    VdpDecoderQueryCapabilities *decoder_query_caps;

    VdpDecoderCreate *create;

    void *func;

    VdpStatus status;

    VdpBool supported;

    uint32_t max_level, max_mb, max_width, max_height;

    VdpChromaType type;

    uint32_t width;

    uint32_t height;

    vdctx->width            = UINT32_MAX;

    vdctx->height           = UINT32_MAX;

    if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height))

        return AVERROR(ENOSYS);

    if (hwctx) {

        hwctx->reset            = 0;

        if (hwctx->context.decoder != VDP_INVALID_HANDLE) {

            vdctx->decoder = hwctx->context.decoder;

            vdctx->render  = hwctx->context.render;

            vdctx->device  = VDP_INVALID_HANDLE;

            return 0; /* Decoder created by user */

        }

        vdctx->device           = hwctx->device;

        vdctx->get_proc_address = hwctx->get_proc_address;

        if (hwctx->flags & AV_HWACCEL_FLAG_IGNORE_LEVEL)

            level = 0;

        if (!(hwctx->flags & AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH) &&

            type != VDP_CHROMA_TYPE_420)

            return AVERROR(ENOSYS);

    } else {

        AVHWFramesContext *frames_ctx = NULL;

        AVVDPAUDeviceContext *dev_ctx;

        // We assume the hw_frames_ctx always survives until ff_vdpau_common_uninit

        // is called. This holds true as the user is not allowed to touch

        // hw_device_ctx, or hw_frames_ctx after get_format (and ff_get_format

        // itself also uninits before unreffing hw_frames_ctx).

        if (avctx->hw_frames_ctx) {

            frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;

        } else if (avctx->hw_device_ctx) {

            int ret;

            avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);

            if (!avctx->hw_frames_ctx)

                return AVERROR(ENOMEM);

            frames_ctx            = (AVHWFramesContext*)avctx->hw_frames_ctx->data;

            frames_ctx->format    = AV_PIX_FMT_VDPAU;

            frames_ctx->sw_format = avctx->sw_pix_fmt;

            frames_ctx->width     = avctx->coded_width;

            frames_ctx->height    = avctx->coded_height;

            ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);

            if (ret < 0) {

                av_buffer_unref(&avctx->hw_frames_ctx);

                return ret;

            }

        }

        if (!frames_ctx) {

            av_log(avctx, AV_LOG_ERROR, "A hardware frames context is "

                   "required for VDPAU decoding.\n");

            return AVERROR(EINVAL);

        }

        dev_ctx = frames_ctx->device_ctx->hwctx;

        vdctx->device           = dev_ctx->device;

        vdctx->get_proc_address = dev_ctx->get_proc_address;

        if (avctx->hwaccel_flags & AV_HWACCEL_FLAG_IGNORE_LEVEL)

            level = 0;

    }

    if (level < 0)

        return AVERROR(ENOTSUP);

    status = vdctx->get_proc_address(vdctx->device,

                                     VDP_FUNC_ID_GET_INFORMATION_STRING,

                                     &func);

    if (status != VDP_STATUS_OK)

        return vdpau_error(status);

    else

        info = func;

    status = info(&info_string);

    if (status != VDP_STATUS_OK)

        return vdpau_error(status);

    if (avctx->codec_id == AV_CODEC_ID_HEVC && strncmp(info_string, "NVIDIA ", 7) == 0 &&

        !(avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH)) {

        av_log(avctx, AV_LOG_VERBOSE, "HEVC with NVIDIA VDPAU drivers is buggy, skipping.\n");

        return AVERROR(ENOTSUP);

    }

    status = vdctx->get_proc_address(vdctx->device,

                                     VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES,

                                     &func);

    if (status != VDP_STATUS_OK)

        return vdpau_error(status);

    else

        surface_query_caps = func;

    status = surface_query_caps(vdctx->device, type, &supported,

                                &max_width, &max_height);

    if (status != VDP_STATUS_OK)

        return vdpau_error(status);

    if (supported != VDP_TRUE ||

        max_width < width || max_height < height)

        return AVERROR(ENOTSUP);

    status = vdctx->get_proc_address(vdctx->device,

                                     VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES,

                                     &func);

    if (status != VDP_STATUS_OK)

        return vdpau_error(status);

    else

        decoder_query_caps = func;

    status = decoder_query_caps(vdctx->device, profile, &supported, &max_level,

                                &max_mb, &max_width, &max_height);

#ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE

    if ((status != VDP_STATUS_OK || supported != VDP_TRUE) && profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE) {

        profile = VDP_DECODER_PROFILE_H264_MAIN;

        status = decoder_query_caps(vdctx->device, profile, &supported,

                                    &max_level, &max_mb,

                                    &max_width, &max_height);

    }

#endif

    if (status != VDP_STATUS_OK)

        return vdpau_error(status);

    if (supported != VDP_TRUE || max_level < level ||

        max_width < width || max_height < height)

        return AVERROR(ENOTSUP);

    status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_CREATE,

                                     &func);

    if (status != VDP_STATUS_OK)

        return vdpau_error(status);

    else

        create = func;

    status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_RENDER,

                                     &func);

    if (status != VDP_STATUS_OK)

        return vdpau_error(status);

    else

        vdctx->render = func;

    status = create(vdctx->device, profile, width, height, avctx->refs,

                    &vdctx->decoder);

    if (status == VDP_STATUS_OK) {

        vdctx->width  = avctx->coded_width;

        vdctx->height = avctx->coded_height;

    }

    return vdpau_error(status);

}


static int idcin_probe(AVProbeData *p)

{

    unsigned int number, sample_rate;

    /*

     * This is what you could call a "probabilistic" file check: id CIN

     * files don't have a definite file signature. In lieu of such a marker,

     * perform sanity checks on the 5 32-bit header fields:

     *  width, height: greater than 0, less than or equal to 1024

     * audio sample rate: greater than or equal to 8000, less than or

     *  equal to 48000, or 0 for no audio

     * audio sample width (bytes/sample): 0 for no audio, or 1 or 2

     * audio channels: 0 for no audio, or 1 or 2

     */

    /* check we have enough data to do all checks, otherwise the

       0-padding may cause a wrong recognition */

    if (p->buf_size < 20)

        return 0;

    /* check the video width */

    number = AV_RL32(&p->buf[0]);

    if ((number == 0) || (number > 1024))

       return 0;

    /* check the video height */

    number = AV_RL32(&p->buf[4]);

    if ((number == 0) || (number > 1024))

       return 0;

    /* check the audio sample rate */

    sample_rate = AV_RL32(&p->buf[8]);

    if (sample_rate && (sample_rate < 8000 || sample_rate > 48000))

        return 0;

    /* check the audio bytes/sample */

    number = AV_RL32(&p->buf[12]);

    if (number > 2 || sample_rate && !number)

        return 0;

    /* check the audio channels */

    number = AV_RL32(&p->buf[16]);

    if (number > 2 || sample_rate && !number)

        return 0;

    /* return half certainty since this check is a bit sketchy */

    return AVPROBE_SCORE_EXTENSION;

}


static inline int hpel_motion(MpegEncContext *s,

                              uint8_t *dest, uint8_t *src,

                              int src_x, int src_y,

                              op_pixels_func *pix_op,

                              int motion_x, int motion_y)

{

    int dxy = 0;

    int emu = 0;

    src_x += motion_x >> 1;

    src_y += motion_y >> 1;

    /* WARNING: do no forget half pels */

    src_x = av_clip(src_x, -16, s->width); // FIXME unneeded for emu?

    if (src_x != s->width)

        dxy |= motion_x & 1;

    src_y = av_clip(src_y, -16, s->height);

    if (src_y != s->height)

        dxy |= (motion_y & 1) << 1;

    src += src_y * s->linesize + src_x;

        if ((unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x & 1) - 8, 0) ||

            (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y & 1) - 8, 0)) {

            s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src,

                                     s->linesize, s->linesize,

                                     9, 9,

                                     src_x, src_y,

                                     s->h_edge_pos, s->v_edge_pos);

            src = s->edge_emu_buffer;

            emu = 1;

        }

    pix_op[dxy](dest, src, s->linesize, 8);

    return emu;

}


static inline void downmix_dualmono_to_mono(float *samples)

{

    int i;

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

        samples[i] += samples[i + 256];

        samples[i + 256] = 0;

    }

}


SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit)

{

    const char *driver;

    DeviceState *dev;

    driver = bdrv_is_sg(dinfo->bdrv) ? "scsi-generic" : "scsi-disk";

    dev = qdev_create(&bus->qbus, driver);

    qdev_prop_set_uint32(dev, "scsi-id", unit);

    qdev_prop_set_drive(dev, "drive", dinfo);

    qdev_init(dev);

    return DO_UPCAST(SCSIDevice, qdev, dev);

}


static int film_read_close(AVFormatContext *s)

{

    FilmDemuxContext *film = s->priv_data;

    av_free(film->sample_table);

    av_free(film->stereo_buffer);

    return 0;

}


static av_cold int libschroedinger_decode_init(AVCodecContext *avctx)

{

    SchroDecoderParams *p_schro_params = avctx->priv_data;

    /* First of all, initialize our supporting libraries. */

    schro_init();

    schro_debug_set_level(avctx->debug);

    p_schro_params->decoder = schro_decoder_new();

    schro_decoder_set_skip_ratio(p_schro_params->decoder, 1);

    if (!p_schro_params->decoder)

        return -1;

    /* Initialize the decoded frame queue. */

    ff_schro_queue_init(&p_schro_params->dec_frame_queue);

    return 0;

}


static void update_stream_timings(AVFormatContext *ic)

{

    int64_t start_time, start_time1, start_time_text, end_time, end_time1;

    int64_t duration, duration1, filesize;

    int i;

    AVStream *st;

    AVProgram *p;

    start_time = INT64_MAX;

    start_time_text = INT64_MAX;

    end_time = INT64_MIN;

    duration = INT64_MIN;

    for(i = 0;i < ic->nb_streams; i++) {

        st = ic->streams[i];

        if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {

            start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);

            if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE || st->codec->codec_type == AVMEDIA_TYPE_DATA) {

                if (start_time1 < start_time_text)

                    start_time_text = start_time1;

            } else

                start_time = FFMIN(start_time, start_time1);

            end_time1 = AV_NOPTS_VALUE;

            if (st->duration != AV_NOPTS_VALUE) {

                end_time1 = start_time1

                          + av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);

                end_time = FFMAX(end_time, end_time1);

            }

            for(p = NULL; (p = av_find_program_from_stream(ic, p, i)); ){

                if(p->start_time == AV_NOPTS_VALUE || p->start_time > start_time1)

                    p->start_time = start_time1;

                if(p->end_time < end_time1)

                    p->end_time = end_time1;

            }

        }

        if (st->duration != AV_NOPTS_VALUE) {

            duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);

            duration = FFMAX(duration, duration1);

        }

    }

    if (start_time == INT64_MAX || (start_time > start_time_text && start_time - start_time_text < AV_TIME_BASE))

        start_time = start_time_text;

    else if(start_time > start_time_text)

        av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream starttime %f\n", start_time_text / (float)AV_TIME_BASE);

    if (start_time != INT64_MAX) {

        ic->start_time = start_time;

        if (end_time != INT64_MIN) {

            if (ic->nb_programs) {

                for (i=0; i<ic->nb_programs; i++) {

                    p = ic->programs[i];

                    if(p->start_time != AV_NOPTS_VALUE && p->end_time > p->start_time)

                        duration = FFMAX(duration, p->end_time - p->start_time);

                }

            } else

                duration = FFMAX(duration, end_time - start_time);

        }

    }

    if (duration != INT64_MIN && duration > 0 && ic->duration == AV_NOPTS_VALUE) {

        ic->duration = duration;

    }

        if (ic->pb && (filesize = avio_size(ic->pb)) > 0 && ic->duration != AV_NOPTS_VALUE) {

            /* compute the bitrate */

            ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE /

                (double)ic->duration;

        }

}


static int sd_open(BlockDriverState *bs, QDict *options, int flags,

                   Error **errp)

{

    int ret, fd;

    uint32_t vid = 0;

    BDRVSheepdogState *s = bs->opaque;

    char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];

    uint32_t snapid;

    char *buf = NULL;

    QemuOpts *opts;

    Error *local_err = NULL;

    const char *filename;

    s->bs = bs;

    s->aio_context = bdrv_get_aio_context(bs);

    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);

    qemu_opts_absorb_qdict(opts, options, &local_err);

    if (local_err) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto err_no_fd;

    }

    filename = qemu_opt_get(opts, "filename");

    QLIST_INIT(&s->inflight_aio_head);

    QLIST_INIT(&s->failed_aio_head);

    QLIST_INIT(&s->inflight_aiocb_head);

    s->fd = -1;

    memset(vdi, 0, sizeof(vdi));

    memset(tag, 0, sizeof(tag));

    if (strstr(filename, "://")) {

        ret = sd_parse_uri(s, filename, vdi, &snapid, tag);

    } else {

        ret = parse_vdiname(s, filename, vdi, &snapid, tag);

    }

    if (ret < 0) {

        error_setg(errp, "Can't parse filename");

        goto err_no_fd;

    }

    s->fd = get_sheep_fd(s, errp);

    if (s->fd < 0) {

        ret = s->fd;

        goto err_no_fd;

    }

    ret = find_vdi_name(s, vdi, snapid, tag, &vid, true, errp);

    if (ret) {

        goto err;

    }

    /*

     * QEMU block layer emulates writethrough cache as 'writeback + flush', so

     * we always set SD_FLAG_CMD_CACHE (writeback cache) as default.

     */

    s->cache_flags = SD_FLAG_CMD_CACHE;

    if (flags & BDRV_O_NOCACHE) {

        s->cache_flags = SD_FLAG_CMD_DIRECT;

    }

    s->discard_supported = true;

    if (snapid || tag[0] != '\0') {

        DPRINTF("%" PRIx32 " snapshot inode was open.\n", vid);

        s->is_snapshot = true;

    }

    fd = connect_to_sdog(s, errp);

    if (fd < 0) {

        ret = fd;

        goto err;

    }

    buf = g_malloc(SD_INODE_SIZE);

    ret = read_object(fd, s->bs, buf, vid_to_vdi_oid(vid),

                      0, SD_INODE_SIZE, 0, s->cache_flags);

    closesocket(fd);

    if (ret) {

        error_setg(errp, "Can't read snapshot inode");

        goto err;

    }

    memcpy(&s->inode, buf, sizeof(s->inode));

    bs->total_sectors = s->inode.vdi_size / BDRV_SECTOR_SIZE;

    pstrcpy(s->name, sizeof(s->name), vdi);

    qemu_co_mutex_init(&s->lock);

    qemu_co_queue_init(&s->overlapping_queue);

    qemu_opts_del(opts);

    g_free(buf);

    return 0;

err:

    aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd,

                       false, NULL, NULL, NULL, NULL);

    closesocket(s->fd);

err_no_fd:

    qemu_opts_del(opts);

    g_free(buf);

    return ret;

}


static void pixel_format_message (VncState *vs) {

    char pad[3] = { 0, 0, 0 };

    vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */

    if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */

    else vnc_write_u8(vs, vs->depth * 8); /* depth */

#ifdef WORDS_BIGENDIAN

    vnc_write_u8(vs, 1);             /* big-endian-flag */

#else

    vnc_write_u8(vs, 0);             /* big-endian-flag */

#endif

    vnc_write_u8(vs, 1);             /* true-color-flag */

    if (vs->depth == 4) {

        vnc_write_u16(vs, 0xFF);     /* red-max */

        vnc_write_u16(vs, 0xFF);     /* green-max */

        vnc_write_u16(vs, 0xFF);     /* blue-max */

        vnc_write_u8(vs, 16);        /* red-shift */

        vnc_write_u8(vs, 8);         /* green-shift */

        vnc_write_u8(vs, 0);         /* blue-shift */

        vs->send_hextile_tile = send_hextile_tile_32;

    } else if (vs->depth == 2) {

        vnc_write_u16(vs, 31);       /* red-max */

        vnc_write_u16(vs, 63);       /* green-max */

        vnc_write_u16(vs, 31);       /* blue-max */

        vnc_write_u8(vs, 11);        /* red-shift */

        vnc_write_u8(vs, 5);         /* green-shift */

        vnc_write_u8(vs, 0);         /* blue-shift */

        vs->send_hextile_tile = send_hextile_tile_16;

    } else if (vs->depth == 1) {

        /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */

        vnc_write_u16(vs, 7);        /* red-max */

        vnc_write_u16(vs, 7);        /* green-max */

        vnc_write_u16(vs, 3);        /* blue-max */

        vnc_write_u8(vs, 5);         /* red-shift */

        vnc_write_u8(vs, 2);         /* green-shift */

        vnc_write_u8(vs, 0);         /* blue-shift */

        vs->send_hextile_tile = send_hextile_tile_8;

    }

    vs->client_red_max = vs->server_red_max;

    vs->client_green_max = vs->server_green_max;

    vs->client_blue_max = vs->server_blue_max;

    vs->client_red_shift = vs->server_red_shift;

    vs->client_green_shift = vs->server_green_shift;

    vs->client_blue_shift = vs->server_blue_shift;

    vs->pix_bpp = vs->depth * 8;

    vs->write_pixels = vnc_write_pixels_copy;

    vnc_write(vs, pad, 3);           /* padding */

}


static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size)

{

    VP56RangeCoder *c = &s->c;

    int header_size, hscale, vscale, i, j, k, l, m, ret;

    int width  = s->avctx->width;

    int height = s->avctx->height;

    s->keyframe  = !(buf[0] & 1);

    s->profile   =  (buf[0]>>1) & 7;

    s->invisible = !(buf[0] & 0x10);

    header_size  = AV_RL24(buf) >> 5;

    buf      += 3;

    buf_size -= 3;

    if (s->profile > 3)

        av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile);

    if (!s->profile)

        memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab));

    else    // profile 1-3 use bilinear, 4+ aren't defined so whatever

        memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_bilinear_pixels_tab, sizeof(s->put_pixels_tab));

    if (header_size > buf_size - 7*s->keyframe) {

        av_log(s->avctx, AV_LOG_ERROR, "Header size larger than data provided\n");

        return AVERROR_INVALIDDATA;

    }

    if (s->keyframe) {

        if (AV_RL24(buf) != 0x2a019d) {

            av_log(s->avctx, AV_LOG_ERROR, "Invalid start code 0x%x\n", AV_RL24(buf));

            return AVERROR_INVALIDDATA;

        }

        width  = AV_RL16(buf+3) & 0x3fff;

        height = AV_RL16(buf+5) & 0x3fff;

        hscale = buf[4] >> 6;

        vscale = buf[6] >> 6;

        buf      += 7;

        buf_size -= 7;

        if (hscale || vscale)

            av_log_missing_feature(s->avctx, "Upscaling", 1);

        s->update_golden = s->update_altref = VP56_FRAME_CURRENT;

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

            for (j = 0; j < 16; j++)

                memcpy(s->prob->token[i][j], vp8_token_default_probs[i][vp8_coeff_band[j]],

                       sizeof(s->prob->token[i][j]));

        memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter, sizeof(s->prob->pred16x16));

        memcpy(s->prob->pred8x8c , vp8_pred8x8c_prob_inter , sizeof(s->prob->pred8x8c));

        memcpy(s->prob->mvc      , vp8_mv_default_prob     , sizeof(s->prob->mvc));

        memset(&s->segmentation, 0, sizeof(s->segmentation));

    }

    if (!s->macroblocks_base || /* first frame */

        width != s->avctx->width || height != s->avctx->height) {

        if ((ret = update_dimensions(s, width, height)) < 0)

            return ret;

    }

    ff_vp56_init_range_decoder(c, buf, header_size);

    buf      += header_size;

    buf_size -= header_size;

    if (s->keyframe) {

        if (vp8_rac_get(c))

            av_log(s->avctx, AV_LOG_WARNING, "Unspecified colorspace\n");

        vp8_rac_get(c); // whether we can skip clamping in dsp functions

    }

    if ((s->segmentation.enabled = vp8_rac_get(c)))

        parse_segment_info(s);

    else

        s->segmentation.update_map = 0; // FIXME: move this to some init function?

    s->filter.simple    = vp8_rac_get(c);

    s->filter.level     = vp8_rac_get_uint(c, 6);

    s->filter.sharpness = vp8_rac_get_uint(c, 3);

    if ((s->lf_delta.enabled = vp8_rac_get(c)))

        if (vp8_rac_get(c))

            update_lf_deltas(s);

    if (setup_partitions(s, buf, buf_size)) {

        av_log(s->avctx, AV_LOG_ERROR, "Invalid partitions\n");

        return AVERROR_INVALIDDATA;

    }

    get_quants(s);

    if (!s->keyframe) {

        update_refs(s);

        s->sign_bias[VP56_FRAME_GOLDEN]               = vp8_rac_get(c);

        s->sign_bias[VP56_FRAME_GOLDEN2 /* altref */] = vp8_rac_get(c);

    }

    // if we aren't saving this frame's probabilities for future frames,

    // make a copy of the current probabilities

    if (!(s->update_probabilities = vp8_rac_get(c)))

        s->prob[1] = s->prob[0];

    s->update_last = s->keyframe || vp8_rac_get(c);

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

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

            for (k = 0; k < 3; k++)

                for (l = 0; l < NUM_DCT_TOKENS-1; l++)

                    if (vp56_rac_get_prob_branchy(c, vp8_token_update_probs[i][j][k][l])) {

                        int prob = vp8_rac_get_uint(c, 8);

                        for (m = 0; vp8_coeff_band_indexes[j][m] >= 0; m++)

                            s->prob->token[i][vp8_coeff_band_indexes[j][m]][k][l] = prob;

                    }

    if ((s->mbskip_enabled = vp8_rac_get(c)))

        s->prob->mbskip = vp8_rac_get_uint(c, 8);

    if (!s->keyframe) {

        s->prob->intra  = vp8_rac_get_uint(c, 8);

        s->prob->last   = vp8_rac_get_uint(c, 8);

        s->prob->golden = vp8_rac_get_uint(c, 8);

        if (vp8_rac_get(c))

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

                s->prob->pred16x16[i] = vp8_rac_get_uint(c, 8);

        if (vp8_rac_get(c))

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

                s->prob->pred8x8c[i]  = vp8_rac_get_uint(c, 8);

        // 17.2 MV probability update

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

            for (j = 0; j < 19; j++)

                if (vp56_rac_get_prob_branchy(c, vp8_mv_update_prob[i][j]))

                    s->prob->mvc[i][j] = vp8_rac_get_nn(c);

    }

    return 0;

}


static int load_refcount_block(BlockDriverState *bs,

                               int64_t refcount_block_offset)

{

    BDRVQcowState *s = bs->opaque;

    int ret;

    if (cache_refcount_updates) {

        ret = write_refcount_block(bs);

        if (ret < 0) {

            return ret;

        }

    }

    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_LOAD);

    ret = bdrv_pread(bs->file, refcount_block_offset, s->refcount_block_cache,

                     s->cluster_size);

    if (ret < 0) {

        return ret;

    }

    s->refcount_block_cache_offset = refcount_block_offset;

    return 0;

}


void qemu_coroutine_enter(Coroutine *co, void *opaque)

{

    Coroutine *self = qemu_coroutine_self();

    CoroutineAction ret;

    trace_qemu_coroutine_enter(self, co, opaque);

    if (co->caller) {

        fprintf(stderr, "Co-routine re-entered recursively\n");

        abort();

    }

    co->caller = self;

    co->entry_arg = opaque;

    ret = qemu_coroutine_switch(self, co, COROUTINE_ENTER);

    qemu_co_queue_run_restart(co);

    switch (ret) {

    case COROUTINE_YIELD:

        return;

    case COROUTINE_TERMINATE:

        trace_qemu_coroutine_terminate(co);

        coroutine_delete(co);

        return;

    default:

        abort();

    }

}


static int imc_decode_frame(AVCodecContext *avctx, void *data,

                            int *got_frame_ptr, AVPacket *avpkt)

{

    AVFrame *frame     = data;

    const uint8_t *buf = avpkt->data;

    int buf_size = avpkt->size;

    int ret, i;

    IMCContext *q = avctx->priv_data;

    LOCAL_ALIGNED_16(uint16_t, buf16, [IMC_BLOCK_SIZE / 2]);

    if (buf_size < IMC_BLOCK_SIZE * avctx->channels) {

        av_log(avctx, AV_LOG_ERROR, "frame too small!\n");

        return AVERROR_INVALIDDATA;

    }

    /* get output buffer */

    frame->nb_samples = COEFFS;

    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)

        return ret;

    for (i = 0; i < avctx->channels; i++) {

        q->out_samples = (float *)frame->extended_data[i];

        q->bdsp.bswap16_buf(buf16, (const uint16_t *) buf, IMC_BLOCK_SIZE / 2);

        init_get_bits(&q->gb, (const uint8_t*)buf16, IMC_BLOCK_SIZE * 8);

        buf += IMC_BLOCK_SIZE;

        if ((ret = imc_decode_block(avctx, q, i)) < 0)

            return ret;

    }

    if (avctx->channels == 2) {

        q->fdsp.butterflies_float((float *)frame->extended_data[0],

                                  (float *)frame->extended_data[1], COEFFS);

    }

    *got_frame_ptr = 1;

    return IMC_BLOCK_SIZE * avctx->channels;

}


int init_vlc(VLC *vlc, int nb_bits, int nb_codes,

             const void *bits, int bits_wrap, int bits_size,

             const void *codes, int codes_wrap, int codes_size)

{

    vlc->bits = nb_bits;

    vlc->table = NULL;

    vlc->table_allocated = 0;

    vlc->table_size = 0;

#ifdef DEBUG_VLC

    printf("build table nb_codes=%d\n", nb_codes);

#endif

    if (build_table(vlc, nb_bits, nb_codes,

                    bits, bits_wrap, bits_size,

                    codes, codes_wrap, codes_size,

                    0, 0) < 0) {

        av_free(vlc->table);

        return -1;

    }

    return 0;

}


static void filter(AVFilterContext *ctx)

{

    IDETContext *idet = ctx->priv;

    int y, i;

    int64_t alpha[2]={0};

    int64_t delta=0;

    Type type, best_type;

    int match = 0;

    for (i = 0; i < idet->csp->nb_components; i++) {

        int w = idet->cur->video->w;

        int h = idet->cur->video->h;

        int refs = idet->cur->linesize[i];

        if (i && i<3) {

            w >>= idet->csp->log2_chroma_w;

            h >>= idet->csp->log2_chroma_h;

        }

        for (y = 2; y < h - 2; y++) {

            uint8_t *prev = &idet->prev->data[i][y*refs];

            uint8_t *cur  = &idet->cur ->data[i][y*refs];

            uint8_t *next = &idet->next->data[i][y*refs];

            alpha[ y   &1] += idet->filter_line(cur-refs, prev, cur+refs, w);

            alpha[(y^1)&1] += idet->filter_line(cur-refs, next, cur+refs, w);

            delta          += idet->filter_line(cur-refs,  cur, cur+refs, w);

        }

    }

    if      (alpha[0] / (float)alpha[1] > idet->interlace_threshold){

        type = TFF;

    }else if(alpha[1] / (float)alpha[0] > idet->interlace_threshold){

        type = BFF;

    }else if(alpha[1] / (float)delta    > idet->progressive_threshold){

        type = PROGRSSIVE;

    }else{

        type = UNDETERMINED;

    }

    memmove(idet->history+1, idet->history, HIST_SIZE-1);

    idet->history[0] = type;

    best_type = UNDETERMINED;

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

        if(idet->history[i] != UNDETERMINED){

            if(best_type == UNDETERMINED)

                best_type = idet->history[i];

            if(idet->history[i] == best_type) {

                match++;

            }else{

                match=0;

                break;

            }

        }

    }

    if(idet->last_type == UNDETERMINED){

        if(match  ) idet->last_type = best_type;

    }else{

        if(match>2) idet->last_type = best_type;

    }

    if      (idet->last_type == TFF){

        idet->cur->video->top_field_first = 1;

        idet->cur->video->interlaced = 1;

    }else if(idet->last_type == BFF){

        idet->cur->video->top_field_first = 0;

        idet->cur->video->interlaced = 1;

    }else if(idet->last_type == PROGRSSIVE){

        idet->cur->video->interlaced = 0;

    }

    idet->prestat [           type] ++;

    idet->poststat[idet->last_type] ++;

    av_log(ctx, AV_LOG_DEBUG, "Single frame:%s, Multi frame:%s\n", type2str(type), type2str(idet->last_type));

}


static void div64(uint64_t *plow, uint64_t *phigh, uint64_t b)

{

    uint64_t q, r, a1, a0;

    int i, qb;

    a0 = *plow;

    a1 = *phigh;

    if (a1 == 0) {

        q = a0 / b;

        r = a0 % b;

        *plow = q;

        *phigh = r;

    } else {

        /* XXX: use a better algorithm */

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

            a1 = (a1 << 1) | (a0 >> 63);

            if (a1 >= b) {

                a1 -= b;

                qb = 1;

            } else {

                qb = 0;

            }

            a0 = (a0 << 1) | qb;

        }

#if defined(DEBUG_MULDIV)

        printf("div: 0x%016llx%016llx / 0x%016llx: q=0x%016llx r=0x%016llx\n",

               *phigh, *plow, b, a0, a1);

#endif

        *plow = a0;

        *phigh = a1;

    }

}


static float get_band_cost_UPAIR12_mips(struct AACEncContext *s,

                                        PutBitContext *pb, const float *in,

                                        const float *scaled, int size, int scale_idx,

                                        int cb, const float lambda, const float uplim,

                                        int *bits)

{

    const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512];

    const float IQ  = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512];

    int i;

    float cost = 0;

    int qc1, qc2, qc3, qc4;

    int curbits = 0;

    uint8_t *p_bits  = (uint8_t *)ff_aac_spectral_bits[cb-1];

    float   *p_codes = (float   *)ff_aac_codebook_vectors[cb-1];

    for (i = 0; i < size; i += 4) {

        const float *vec, *vec2;

        int curidx, curidx2;

        int sign1, count1, sign2, count2;

        int   *in_int = (int   *)&in[i];

        float *in_pos = (float *)&in[i];

        float di0, di1, di2, di3;

        int t0, t1, t2, t3, t4;

        qc1 = scaled[i  ] * Q34 + ROUND_STANDARD;

        qc2 = scaled[i+1] * Q34 + ROUND_STANDARD;

        qc3 = scaled[i+2] * Q34 + ROUND_STANDARD;

        qc4 = scaled[i+3] * Q34 + ROUND_STANDARD;

        __asm__ volatile (

            ".set push                                          \n\t"

            ".set noreorder                                     \n\t"

            "ori        %[t4],      $zero,      12              \n\t"

            "ori        %[sign1],   $zero,      0               \n\t"

            "ori        %[sign2],   $zero,      0               \n\t"

            "slt        %[t0],      %[t4],      %[qc1]          \n\t"

            "slt        %[t1],      %[t4],      %[qc2]          \n\t"

            "slt        %[t2],      %[t4],      %[qc3]          \n\t"

            "slt        %[t3],      %[t4],      %[qc4]          \n\t"

            "movn       %[qc1],     %[t4],      %[t0]           \n\t"

            "movn       %[qc2],     %[t4],      %[t1]           \n\t"

            "movn       %[qc3],     %[t4],      %[t2]           \n\t"

            "movn       %[qc4],     %[t4],      %[t3]           \n\t"

            "lw         %[t0],      0(%[in_int])                \n\t"

            "lw         %[t1],      4(%[in_int])                \n\t"

            "lw         %[t2],      8(%[in_int])                \n\t"

            "lw         %[t3],      12(%[in_int])               \n\t"

            "slt        %[t0],      %[t0],      $zero           \n\t"

            "movn       %[sign1],   %[t0],      %[qc1]          \n\t"

            "slt        %[t2],      %[t2],      $zero           \n\t"

            "movn       %[sign2],   %[t2],      %[qc3]          \n\t"

            "slt        %[t1],      %[t1],      $zero           \n\t"

            "sll        %[t0],      %[sign1],   1               \n\t"

            "or         %[t0],      %[t0],      %[t1]           \n\t"

            "movn       %[sign1],   %[t0],      %[qc2]          \n\t"

            "slt        %[t3],      %[t3],      $zero           \n\t"

            "sll        %[t0],      %[sign2],   1               \n\t"

            "or         %[t0],      %[t0],      %[t3]           \n\t"

            "movn       %[sign2],   %[t0],      %[qc4]          \n\t"

            "slt        %[count1],  $zero,      %[qc1]          \n\t"

            "slt        %[t1],      $zero,      %[qc2]          \n\t"

            "slt        %[count2],  $zero,      %[qc3]          \n\t"

            "slt        %[t2],      $zero,      %[qc4]          \n\t"

            "addu       %[count1],  %[count1],  %[t1]           \n\t"

            "addu       %[count2],  %[count2],  %[t2]           \n\t"

            ".set pop                                           \n\t"

            : [qc1]"+r"(qc1), [qc2]"+r"(qc2),

              [qc3]"+r"(qc3), [qc4]"+r"(qc4),

              [sign1]"=&r"(sign1), [count1]"=&r"(count1),

              [sign2]"=&r"(sign2), [count2]"=&r"(count2),

              [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3),

              [t4]"=&r"(t4)

            : [in_int]"r"(in_int)

            : "memory"

        );

        curidx = 13 * qc1;

        curidx += qc2;

        curidx2 = 13 * qc3;

        curidx2 += qc4;

        curbits += p_bits[curidx];

        curbits += p_bits[curidx2];

        curbits += upair12_sign_bits[curidx];

        curbits += upair12_sign_bits[curidx2];

        vec     = &p_codes[curidx*2];

        vec2    = &p_codes[curidx2*2];

        __asm__ volatile (

            ".set push                                          \n\t"

            ".set noreorder                                     \n\t"

            "lwc1       %[di0],     0(%[in_pos])                \n\t"

            "lwc1       %[di1],     4(%[in_pos])                \n\t"

            "lwc1       %[di2],     8(%[in_pos])                \n\t"

            "lwc1       %[di3],     12(%[in_pos])               \n\t"

            "abs.s      %[di0],     %[di0]                      \n\t"

            "abs.s      %[di1],     %[di1]                      \n\t"

            "abs.s      %[di2],     %[di2]                      \n\t"

            "abs.s      %[di3],     %[di3]                      \n\t"

            "lwc1       $f0,        0(%[vec])                   \n\t"

            "lwc1       $f1,        4(%[vec])                   \n\t"

            "lwc1       $f2,        0(%[vec2])                  \n\t"

            "lwc1       $f3,        4(%[vec2])                  \n\t"

            "nmsub.s    %[di0],     %[di0],     $f0,    %[IQ]   \n\t"

            "nmsub.s    %[di1],     %[di1],     $f1,    %[IQ]   \n\t"

            "nmsub.s    %[di2],     %[di2],     $f2,    %[IQ]   \n\t"

            "nmsub.s    %[di3],     %[di3],     $f3,    %[IQ]   \n\t"

            ".set pop                                           \n\t"

            : [di0]"=&f"(di0), [di1]"=&f"(di1),

              [di2]"=&f"(di2), [di3]"=&f"(di3)

            : [in_pos]"r"(in_pos), [vec]"r"(vec),

              [vec2]"r"(vec2), [IQ]"f"(IQ)

            : "$f0", "$f1", "$f2", "$f3",

              "memory"

        );

        cost += di0 * di0 + di1 * di1

                + di2 * di2 + di3 * di3;

    }

    if (bits)

        *bits = curbits;

    return cost * lambda + curbits;

}


static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image)

{

    int compno;

    int x;

    int y;

    int width;

    int height;

    int *image_line;

    int frame_index;

    const int numcomps = image->numcomps;

    uint16_t *frame_ptr;

    for (compno = 0; compno < numcomps; ++compno) {

        if (image->comps[compno].w > frame->linesize[compno]) {

            av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n");

            return 0;

        }

    }

    for (compno = 0; compno < numcomps; ++compno) {

        width     = avctx->width / image->comps[compno].dx;

        height    = avctx->height / image->comps[compno].dy;

        frame_ptr = (uint16_t *)frame->data[compno];

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

            image_line = image->comps[compno].data + y * image->comps[compno].w;

            frame_index = y * (frame->linesize[compno] / 2);

            for (x = 0; x < width; ++x)

                image_line[x] = frame_ptr[frame_index++];

            for (; x < image->comps[compno].w; ++x) {

                image_line[x] = image_line[x - 1];

            }

        }

        for (; y < image->comps[compno].h; ++y) {

            image_line = image->comps[compno].data + y * image->comps[compno].w;

            for (x = 0; x < image->comps[compno].w; ++x) {

                image_line[x] = image_line[x - image->comps[compno].w];

            }

        }

    }

    return 1;

}


inline static void RENAME(hcscale)(uint16_t *dst, int dstWidth, uint8_t *src1, uint8_t *src2,

				   int srcW, int xInc, int flags, int canMMX2BeUsed, int16_t *hChrFilter,

				   int16_t *hChrFilterPos, int hChrFilterSize, void *funnyUVCode,

				   int srcFormat, uint8_t *formatConvBuffer, int16_t *mmx2Filter,

				   int32_t *mmx2FilterPos)

{

    if(srcFormat==IMGFMT_YUY2)

    {

	RENAME(yuy2ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);

	src1= formatConvBuffer;

	src2= formatConvBuffer+2048;

    }

    else if(srcFormat==IMGFMT_UYVY)

    {

	RENAME(uyvyToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);

	src1= formatConvBuffer;

	src2= formatConvBuffer+2048;

    }

    else if(srcFormat==IMGFMT_BGR32)

    {

	RENAME(bgr32ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);

	src1= formatConvBuffer;

	src2= formatConvBuffer+2048;

    }

    else if(srcFormat==IMGFMT_BGR24)

    {

	RENAME(bgr24ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);

	src1= formatConvBuffer;

	src2= formatConvBuffer+2048;

    }

    else if(srcFormat==IMGFMT_BGR16)

    {

	RENAME(bgr16ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);

	src1= formatConvBuffer;

	src2= formatConvBuffer+2048;

    }

    else if(srcFormat==IMGFMT_BGR15)

    {

	RENAME(bgr15ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);

	src1= formatConvBuffer;

	src2= formatConvBuffer+2048;

    }

    else if(srcFormat==IMGFMT_RGB32)

    {

	RENAME(rgb32ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);

	src1= formatConvBuffer;

	src2= formatConvBuffer+2048;

    }

    else if(srcFormat==IMGFMT_RGB24)

    {

	RENAME(rgb24ToUV)(formatConvBuffer, formatConvBuffer+2048, src1, src2, srcW);

	src1= formatConvBuffer;

	src2= formatConvBuffer+2048;

    }

    else if(isGray(srcFormat))

    {

    	return;

    }

#ifdef HAVE_MMX

	// use the new MMX scaler if the mmx2 can't be used (its faster than the x86asm one)

    if(!(flags&SWS_FAST_BILINEAR) || (!canMMX2BeUsed))

#else

    if(!(flags&SWS_FAST_BILINEAR))

#endif

    {

    	RENAME(hScale)(dst     , dstWidth, src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);

    	RENAME(hScale)(dst+2048, dstWidth, src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);

    }

    else // Fast Bilinear upscale / crap downscale

    {

#if defined(ARCH_X86) || defined(ARCH_X86_64)

#ifdef HAVE_MMX2

	int i;

	if(canMMX2BeUsed)

	{

		asm volatile(

			"pxor %%mm7, %%mm7		\n\t"

			"mov %0, %%"REG_c"		\n\t"

			"mov %1, %%"REG_D"		\n\t"

			"mov %2, %%"REG_d"		\n\t"

			"mov %3, %%"REG_b"		\n\t"

			"xor %%"REG_a", %%"REG_a"	\n\t" // i

			PREFETCH" (%%"REG_c")		\n\t"

			PREFETCH" 32(%%"REG_c")		\n\t"

			PREFETCH" 64(%%"REG_c")		\n\t"

#ifdef ARCH_X86_64

#define FUNNY_UV_CODE \

			"movl (%%"REG_b"), %%esi	\n\t"\

			"call *%4			\n\t"\

			"movl (%%"REG_b", %%"REG_a"), %%esi\n\t"\

			"add %%"REG_S", %%"REG_c"	\n\t"\

			"add %%"REG_a", %%"REG_D"	\n\t"\

			"xor %%"REG_a", %%"REG_a"	\n\t"\

#else

#define FUNNY_UV_CODE \

			"movl (%%"REG_b"), %%esi	\n\t"\

			"call *%4			\n\t"\

			"addl (%%"REG_b", %%"REG_a"), %%"REG_c"\n\t"\

			"add %%"REG_a", %%"REG_D"	\n\t"\

			"xor %%"REG_a", %%"REG_a"	\n\t"\

#endif

FUNNY_UV_CODE

FUNNY_UV_CODE

FUNNY_UV_CODE

FUNNY_UV_CODE

			"xor %%"REG_a", %%"REG_a"	\n\t" // i

			"mov %5, %%"REG_c"		\n\t" // src

			"mov %1, %%"REG_D"		\n\t" // buf1

			"add $4096, %%"REG_D"		\n\t"

			PREFETCH" (%%"REG_c")		\n\t"

			PREFETCH" 32(%%"REG_c")		\n\t"

			PREFETCH" 64(%%"REG_c")		\n\t"

FUNNY_UV_CODE

FUNNY_UV_CODE

FUNNY_UV_CODE

FUNNY_UV_CODE

			:: "m" (src1), "m" (dst), "m" (mmx2Filter), "m" (mmx2FilterPos),

			"m" (funnyUVCode), "m" (src2)

			: "%"REG_a, "%"REG_b, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D

		);

		for(i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)

		{

//			printf("%d %d %d\n", dstWidth, i, srcW);

			dst[i] = src1[srcW-1]*128;

			dst[i+2048] = src2[srcW-1]*128;

		}

	}

	else

	{

#endif

	long xInc_shr16 = (long) (xInc >> 16);

	int xInc_mask = xInc & 0xffff;

	asm volatile(

		"xor %%"REG_a", %%"REG_a"	\n\t" // i

		"xor %%"REG_b", %%"REG_b"		\n\t" // xx

		"xorl %%ecx, %%ecx		\n\t" // 2*xalpha

		".balign 16			\n\t"

		"1:				\n\t"

		"mov %0, %%"REG_S"		\n\t"

		"movzbl  (%%"REG_S", %%"REG_b"), %%edi	\n\t" //src[xx]

		"movzbl 1(%%"REG_S", %%"REG_b"), %%esi	\n\t" //src[xx+1]

		"subl %%edi, %%esi		\n\t" //src[xx+1] - src[xx]

		"imull %%ecx, %%esi		\n\t" //(src[xx+1] - src[xx])*2*xalpha

		"shll $16, %%edi		\n\t"

		"addl %%edi, %%esi		\n\t" //src[xx+1]*2*xalpha + src[xx]*(1-2*xalpha)

		"mov %1, %%"REG_D"		\n\t"

		"shrl $9, %%esi			\n\t"

		"movw %%si, (%%"REG_D", %%"REG_a", 2)\n\t"

		"movzbl  (%5, %%"REG_b"), %%edi	\n\t" //src[xx]

		"movzbl 1(%5, %%"REG_b"), %%esi	\n\t" //src[xx+1]

		"subl %%edi, %%esi		\n\t" //src[xx+1] - src[xx]

		"imull %%ecx, %%esi		\n\t" //(src[xx+1] - src[xx])*2*xalpha

		"shll $16, %%edi		\n\t"

		"addl %%edi, %%esi		\n\t" //src[xx+1]*2*xalpha + src[xx]*(1-2*xalpha)

		"mov %1, %%"REG_D"		\n\t"

		"shrl $9, %%esi			\n\t"

		"movw %%si, 4096(%%"REG_D", %%"REG_a", 2)\n\t"

		"addw %4, %%cx			\n\t" //2*xalpha += xInc&0xFF

		"adc %3, %%"REG_b"		\n\t" //xx+= xInc>>8 + carry

		"add $1, %%"REG_a"		\n\t"

		"cmp %2, %%"REG_a"		\n\t"

		" jb 1b				\n\t"

/* GCC-3.3 makes MPlayer crash on IA-32 machines when using "g" operand here,

   which is needed to support GCC-4.0 */

#if defined(ARCH_X86_64) && ((__GNUC__ > 3) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4))

		:: "m" (src1), "m" (dst), "g" ((long)dstWidth), "m" (xInc_shr16), "m" (xInc_mask),

#else

		:: "m" (src1), "m" (dst), "m" ((long)dstWidth), "m" (xInc_shr16), "m" (xInc_mask),

#endif

		"r" (src2)

		: "%"REG_a, "%"REG_b, "%ecx", "%"REG_D, "%esi"

		);

#ifdef HAVE_MMX2

	} //if MMX2 can't be used

#endif

#else

	int i;

	unsigned int xpos=0;

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

	{

		register unsigned int xx=xpos>>16;

		register unsigned int xalpha=(xpos&0xFFFF)>>9;

		dst[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha);

		dst[i+2048]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);

/* slower

	  dst[i]= (src1[xx]<<7) + (src1[xx+1] - src1[xx])*xalpha;

	  dst[i+2048]=(src2[xx]<<7) + (src2[xx+1] - src2[xx])*xalpha;

*/

		xpos+=xInc;

	}

#endif

   }

}


static int tak_read_header(AVFormatContext *s)

{

    TAKDemuxContext *tc = s->priv_data;

    AVIOContext *pb     = s->pb;

    GetBitContext gb;

    AVStream *st;

    uint8_t *buffer = NULL;

    int ret;

    st = avformat_new_stream(s, 0);

    if (!st)

        return AVERROR(ENOMEM);

    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;

    st->codec->codec_id   = AV_CODEC_ID_TAK;

    st->need_parsing      = AVSTREAM_PARSE_FULL_RAW;

    tc->mlast_frame = 0;

    if (avio_rl32(pb) != MKTAG('t', 'B', 'a', 'K')) {

        avio_seek(pb, -4, SEEK_CUR);

        return 0;

    }

    while (!url_feof(pb)) {

        enum TAKMetaDataType type;

        int size;

        type = avio_r8(pb) & 0x7f;

        size = avio_rl24(pb);

        switch (type) {

        case TAK_METADATA_STREAMINFO:

        case TAK_METADATA_LAST_FRAME:

        case TAK_METADATA_ENCODER:

            if (size <= 3)

                return AVERROR_INVALIDDATA;

            buffer = av_malloc(size - 3 + FF_INPUT_BUFFER_PADDING_SIZE);

            if (!buffer)

                return AVERROR(ENOMEM);

            ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U);

            if (avio_read(pb, buffer, size - 3) != size - 3) {

                av_freep(&buffer);

                return AVERROR(EIO);

            }

            if (ffio_get_checksum(s->pb) != avio_rb24(pb)) {

                av_log(s, AV_LOG_ERROR, "%d metadata block CRC error.\n", type);

                if (s->error_recognition & AV_EF_EXPLODE) {

                    av_freep(&buffer);

                    return AVERROR_INVALIDDATA;

                }

            }

            init_get_bits8(&gb, buffer, size - 3);

            break;

        case TAK_METADATA_MD5: {

            uint8_t md5[16];

            int i;

            if (size != 19)

                return AVERROR_INVALIDDATA;

            ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U);

            avio_read(pb, md5, 16);

            if (ffio_get_checksum(s->pb) != avio_rb24(pb)) {

                av_log(s, AV_LOG_ERROR, "MD5 metadata block CRC error.\n");

                if (s->error_recognition & AV_EF_EXPLODE)

                    return AVERROR_INVALIDDATA;

            }

            av_log(s, AV_LOG_VERBOSE, "MD5=");

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

                av_log(s, AV_LOG_VERBOSE, "%02x", md5[i]);

            av_log(s, AV_LOG_VERBOSE, "\n");

            break;

        }

        case TAK_METADATA_END: {

            int64_t curpos = avio_tell(pb);

            if (pb->seekable) {

                ff_ape_parse_tag(s);

                avio_seek(pb, curpos, SEEK_SET);

            }

            tc->data_end += curpos;

            return 0;

        }

        default:

            ret = avio_skip(pb, size);

            if (ret < 0)

                return ret;

        }

        if (type == TAK_METADATA_STREAMINFO) {

            TAKStreamInfo ti;

            avpriv_tak_parse_streaminfo(&gb, &ti);

            if (ti.samples > 0)

                st->duration = ti.samples;

            st->codec->bits_per_coded_sample = ti.bps;

            if (ti.ch_layout)

                st->codec->channel_layout = ti.ch_layout;

            st->codec->sample_rate           = ti.sample_rate;

            st->codec->channels              = ti.channels;

            st->start_time                   = 0;

            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);

            st->codec->extradata             = buffer;

            st->codec->extradata_size        = size - 3;

            buffer                           = NULL;

        } else if (type == TAK_METADATA_LAST_FRAME) {

            if (size != 11)

                return AVERROR_INVALIDDATA;

            tc->mlast_frame = 1;

            tc->data_end    = get_bits64(&gb, TAK_LAST_FRAME_POS_BITS) +

                              get_bits(&gb, TAK_LAST_FRAME_SIZE_BITS);

            av_freep(&buffer);

        } else if (type == TAK_METADATA_ENCODER) {

            av_log(s, AV_LOG_VERBOSE, "encoder version: %0X\n",

                   get_bits_long(&gb, TAK_ENCODER_VERSION_BITS));

            av_freep(&buffer);

        }

    }

    return AVERROR_EOF;

}


static void cpu_pre_save(void *opaque)

{

    CPUState *env = opaque;

    int i;

    cpu_synchronize_state(env);

    /* FPU */

    env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;

    env->fptag_vmstate = 0;

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

        env->fptag_vmstate |= ((!env->fptags[i]) << i);

    }

#ifdef USE_X86LDOUBLE

    env->fpregs_format_vmstate = 0;

#else

    env->fpregs_format_vmstate = 1;

#endif

}


static uint64_t ich_elrsr_read(CPUARMState *env, const ARMCPRegInfo *ri)

{

    GICv3CPUState *cs = icc_cs_from_env(env);

    uint64_t value = 0;

    int i;

    for (i = 0; i < cs->num_list_regs; i++) {

        uint64_t lr = cs->ich_lr_el2[i];

        if ((lr & ICH_LR_EL2_STATE_MASK) == 0 &&

            ((lr & ICH_LR_EL2_HW) == 1 || (lr & ICH_LR_EL2_EOI) == 0)) {

            value |= (1 << i);

        }

    }

    trace_gicv3_ich_elrsr_read(gicv3_redist_affid(cs), value);

    return value;

}


static int mp_user_removexattr(FsContext *ctx,

                               const char *path, const char *name)

{

    char *buffer;

    int ret;

    if (strncmp(name, "user.virtfs.", 12) == 0) {

        /*

         * Don't allow fetch of user.virtfs namesapce

         * in case of mapped security

         */

        errno = EACCES;

        return -1;

    }

    buffer = rpath(ctx, path);

    ret = lremovexattr(buffer, name);

    g_free(buffer);

    return ret;

}