int ff_h264_decode_mb_cabac(H264Context *h) {

    MpegEncContext * const s = &h->s;

    int mb_xy;

    int mb_type, partition_count, cbp = 0;

    int dct8x8_allowed= h->pps.transform_8x8_mode;

    mb_xy = h->mb_xy = s->mb_x + s->mb_y*s->mb_stride;

    tprintf(s->avctx, "pic:%d mb:%d/%d\n", h->frame_num, s->mb_x, s->mb_y);

    if( h->slice_type_nos != FF_I_TYPE ) {

        int skip;

        /* a skipped mb needs the aff flag from the following mb */

        if( FRAME_MBAFF && s->mb_x==0 && (s->mb_y&1)==0 )

            predict_field_decoding_flag(h);

        if( FRAME_MBAFF && (s->mb_y&1)==1 && h->prev_mb_skipped )

            skip = h->next_mb_skipped;

        else

            skip = decode_cabac_mb_skip( h, s->mb_x, s->mb_y );

        /* read skip flags */

        if( skip ) {

            if( FRAME_MBAFF && (s->mb_y&1)==0 ){

                s->current_picture.mb_type[mb_xy] = MB_TYPE_SKIP;

                h->next_mb_skipped = decode_cabac_mb_skip( h, s->mb_x, s->mb_y+1 );

                if(!h->next_mb_skipped)

                    h->mb_mbaff = h->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h);

            }

            decode_mb_skip(h);

            h->cbp_table[mb_xy] = 0;

            h->chroma_pred_mode_table[mb_xy] = 0;

            h->last_qscale_diff = 0;

            return 0;

        }

    }

    if(FRAME_MBAFF){

        if( (s->mb_y&1) == 0 )

            h->mb_mbaff =

            h->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h);

    }

    h->prev_mb_skipped = 0;

    compute_mb_neighbors(h);

    if( h->slice_type_nos == FF_B_TYPE ) {

        mb_type = decode_cabac_mb_type_b( h );

        if( mb_type < 23 ){

            partition_count= b_mb_type_info[mb_type].partition_count;

            mb_type=         b_mb_type_info[mb_type].type;

        }else{

            mb_type -= 23;

            goto decode_intra_mb;

        }

    } else if( h->slice_type_nos == FF_P_TYPE ) {

        if( get_cabac_noinline( &h->cabac, &h->cabac_state[14] ) == 0 ) {

            /* P-type */

            if( get_cabac_noinline( &h->cabac, &h->cabac_state[15] ) == 0 ) {

                /* P_L0_D16x16, P_8x8 */

                mb_type= 3 * get_cabac_noinline( &h->cabac, &h->cabac_state[16] );

            } else {

                /* P_L0_D8x16, P_L0_D16x8 */

                mb_type= 2 - get_cabac_noinline( &h->cabac, &h->cabac_state[17] );

            }

            partition_count= p_mb_type_info[mb_type].partition_count;

            mb_type=         p_mb_type_info[mb_type].type;

        } else {

            mb_type= decode_cabac_intra_mb_type(h, 17, 0);

            goto decode_intra_mb;

        }

    } else {

        mb_type= decode_cabac_intra_mb_type(h, 3, 1);

        if(h->slice_type == FF_SI_TYPE && mb_type)

            mb_type--;

        assert(h->slice_type_nos == FF_I_TYPE);

decode_intra_mb:

        partition_count = 0;

        cbp= i_mb_type_info[mb_type].cbp;

        h->intra16x16_pred_mode= i_mb_type_info[mb_type].pred_mode;

        mb_type= i_mb_type_info[mb_type].type;

    }

    if(MB_FIELD)

        mb_type |= MB_TYPE_INTERLACED;

    h->slice_table[ mb_xy ]= h->slice_num;

    if(IS_INTRA_PCM(mb_type)) {

        const uint8_t *ptr;

        // We assume these blocks are very rare so we do not optimize it.

        // FIXME The two following lines get the bitstream position in the cabac

        // decode, I think it should be done by a function in cabac.h (or cabac.c).

        ptr= h->cabac.bytestream;

        if(h->cabac.low&0x1) ptr--;

        if(CABAC_BITS==16){

            if(h->cabac.low&0x1FF) ptr--;

        }

        // The pixels are stored in the same order as levels in h->mb array.

        memcpy(h->mb, ptr, 256); ptr+=256;

        if(CHROMA){

            memcpy(h->mb+128, ptr, 128); ptr+=128;

        }

        ff_init_cabac_decoder(&h->cabac, ptr, h->cabac.bytestream_end - ptr);

        // All blocks are present

        h->cbp_table[mb_xy] = 0x1ef;

        h->chroma_pred_mode_table[mb_xy] = 0;

        // In deblocking, the quantizer is 0

        s->current_picture.qscale_table[mb_xy]= 0;

        // All coeffs are present

        memset(h->non_zero_count[mb_xy], 16, 16);

        s->current_picture.mb_type[mb_xy]= mb_type;

        h->last_qscale_diff = 0;

        return 0;

    }

    if(MB_MBAFF){

        h->ref_count[0] <<= 1;

        h->ref_count[1] <<= 1;

    }

    fill_caches(h, mb_type, 0);

    if( IS_INTRA( mb_type ) ) {

        int i, pred_mode;

        if( IS_INTRA4x4( mb_type ) ) {

            if( dct8x8_allowed && decode_cabac_mb_transform_size( h ) ) {

                mb_type |= MB_TYPE_8x8DCT;

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

                    int pred = pred_intra_mode( h, i );

                    int mode = decode_cabac_mb_intra4x4_pred_mode( h, pred );

                    fill_rectangle( &h->intra4x4_pred_mode_cache[ scan8[i] ], 2, 2, 8, mode, 1 );

                }

            } else {

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

                    int pred = pred_intra_mode( h, i );

                    h->intra4x4_pred_mode_cache[ scan8[i] ] = decode_cabac_mb_intra4x4_pred_mode( h, pred );

                //av_log( s->avctx, AV_LOG_ERROR, "i4x4 pred=%d mode=%d\n", pred, h->intra4x4_pred_mode_cache[ scan8[i] ] );

                }

            }

            ff_h264_write_back_intra_pred_mode(h);

            if( ff_h264_check_intra4x4_pred_mode(h) < 0 ) return -1;

        } else {

            h->intra16x16_pred_mode= ff_h264_check_intra_pred_mode( h, h->intra16x16_pred_mode );

            if( h->intra16x16_pred_mode < 0 ) return -1;

        }

        if(CHROMA){

            h->chroma_pred_mode_table[mb_xy] =

            pred_mode                        = decode_cabac_mb_chroma_pre_mode( h );

            pred_mode= ff_h264_check_intra_pred_mode( h, pred_mode );

            if( pred_mode < 0 ) return -1;

            h->chroma_pred_mode= pred_mode;

        }

    } else if( partition_count == 4 ) {

        int i, j, sub_partition_count[4], list, ref[2][4];

        if( h->slice_type_nos == FF_B_TYPE ) {

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

                h->sub_mb_type[i] = decode_cabac_b_mb_sub_type( h );

                sub_partition_count[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count;

                h->sub_mb_type[i]=      b_sub_mb_type_info[ h->sub_mb_type[i] ].type;

            }

            if( IS_DIRECT(h->sub_mb_type[0] | h->sub_mb_type[1] |

                          h->sub_mb_type[2] | h->sub_mb_type[3]) ) {

                ff_h264_pred_direct_motion(h, &mb_type);

                h->ref_cache[0][scan8[4]] =

                h->ref_cache[1][scan8[4]] =

                h->ref_cache[0][scan8[12]] =

                h->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE;

                if( h->ref_count[0] > 1 || h->ref_count[1] > 1 ) {

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

                        if( IS_DIRECT(h->sub_mb_type[i]) )

                            fill_rectangle( &h->direct_cache[scan8[4*i]], 2, 2, 8, 1, 1 );

                }

            }

        } else {

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

                h->sub_mb_type[i] = decode_cabac_p_mb_sub_type( h );

                sub_partition_count[i]= p_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count;

                h->sub_mb_type[i]=      p_sub_mb_type_info[ h->sub_mb_type[i] ].type;

            }

        }

        for( list = 0; list < h->list_count; list++ ) {

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

                    if(IS_DIRECT(h->sub_mb_type[i])) continue;

                    if(IS_DIR(h->sub_mb_type[i], 0, list)){

                        if( h->ref_count[list] > 1 ){

                            ref[list][i] = decode_cabac_mb_ref( h, list, 4*i );

                            if(ref[list][i] >= (unsigned)h->ref_count[list]){

                                av_log(s->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref[list][i], h->ref_count[list]);

                                return -1;

                            }

                        }else

                            ref[list][i] = 0;

                    } else {

                        ref[list][i] = -1;

                    }

                                                       h->ref_cache[list][ scan8[4*i]+1 ]=

                    h->ref_cache[list][ scan8[4*i]+8 ]=h->ref_cache[list][ scan8[4*i]+9 ]= ref[list][i];

                }

        }

        if(dct8x8_allowed)

            dct8x8_allowed = get_dct8x8_allowed(h);

        for(list=0; list<h->list_count; list++){

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

                h->ref_cache[list][ scan8[4*i]   ]=h->ref_cache[list][ scan8[4*i]+1 ];

                if(IS_DIRECT(h->sub_mb_type[i])){

                    fill_rectangle(h->mvd_cache[list][scan8[4*i]], 2, 2, 8, 0, 4);

                    continue;

                }

                if(IS_DIR(h->sub_mb_type[i], 0, list) && !IS_DIRECT(h->sub_mb_type[i])){

                    const int sub_mb_type= h->sub_mb_type[i];

                    const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1;

                    for(j=0; j<sub_partition_count[i]; j++){

                        int mpx, mpy;

                        int mx, my;

                        const int index= 4*i + block_width*j;

                        int16_t (* mv_cache)[2]= &h->mv_cache[list][ scan8[index] ];

                        int16_t (* mvd_cache)[2]= &h->mvd_cache[list][ scan8[index] ];

                        pred_motion(h, index, block_width, list, h->ref_cache[list][ scan8[index] ], &mpx, &mpy);

                        mx = mpx + decode_cabac_mb_mvd( h, list, index, 0 );

                        my = mpy + decode_cabac_mb_mvd( h, list, index, 1 );

                        tprintf(s->avctx, "final mv:%d %d\n", mx, my);

                        if(IS_SUB_8X8(sub_mb_type)){

                            mv_cache[ 1 ][0]=

                            mv_cache[ 8 ][0]= mv_cache[ 9 ][0]= mx;

                            mv_cache[ 1 ][1]=

                            mv_cache[ 8 ][1]= mv_cache[ 9 ][1]= my;

                            mvd_cache[ 1 ][0]=

                            mvd_cache[ 8 ][0]= mvd_cache[ 9 ][0]= mx - mpx;

                            mvd_cache[ 1 ][1]=

                            mvd_cache[ 8 ][1]= mvd_cache[ 9 ][1]= my - mpy;

                        }else if(IS_SUB_8X4(sub_mb_type)){

                            mv_cache[ 1 ][0]= mx;

                            mv_cache[ 1 ][1]= my;

                            mvd_cache[ 1 ][0]= mx - mpx;

                            mvd_cache[ 1 ][1]= my - mpy;

                        }else if(IS_SUB_4X8(sub_mb_type)){

                            mv_cache[ 8 ][0]= mx;

                            mv_cache[ 8 ][1]= my;

                            mvd_cache[ 8 ][0]= mx - mpx;

                            mvd_cache[ 8 ][1]= my - mpy;

                        }

                        mv_cache[ 0 ][0]= mx;

                        mv_cache[ 0 ][1]= my;

                        mvd_cache[ 0 ][0]= mx - mpx;

                        mvd_cache[ 0 ][1]= my - mpy;

                    }

                }else{

                    uint32_t *p= (uint32_t *)&h->mv_cache[list][ scan8[4*i] ][0];

                    uint32_t *pd= (uint32_t *)&h->mvd_cache[list][ scan8[4*i] ][0];

                    p[0] = p[1] = p[8] = p[9] = 0;

                    pd[0]= pd[1]= pd[8]= pd[9]= 0;

                }

            }

        }

    } else if( IS_DIRECT(mb_type) ) {

        ff_h264_pred_direct_motion(h, &mb_type);

        fill_rectangle(h->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 4);

        fill_rectangle(h->mvd_cache[1][scan8[0]], 4, 4, 8, 0, 4);

        dct8x8_allowed &= h->sps.direct_8x8_inference_flag;

    } else {

        int list, mx, my, i, mpx, mpy;

        if(IS_16X16(mb_type)){

            for(list=0; list<h->list_count; list++){

                if(IS_DIR(mb_type, 0, list)){

                    int ref;

                    if(h->ref_count[list] > 1){

                        ref= decode_cabac_mb_ref(h, list, 0);

                        if(ref >= (unsigned)h->ref_count[list]){

                            av_log(s->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, h->ref_count[list]);

                            return -1;

                        }

                    }else

                        ref=0;

                        fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1);

                }else

                    fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, (uint8_t)LIST_NOT_USED, 1); //FIXME factorize and the other fill_rect below too

            }

            for(list=0; list<h->list_count; list++){

                if(IS_DIR(mb_type, 0, list)){

                    pred_motion(h, 0, 4, list, h->ref_cache[list][ scan8[0] ], &mpx, &mpy);

                    mx = mpx + decode_cabac_mb_mvd( h, list, 0, 0 );

                    my = mpy + decode_cabac_mb_mvd( h, list, 0, 1 );

                    tprintf(s->avctx, "final mv:%d %d\n", mx, my);

                    fill_rectangle(h->mvd_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx-mpx,my-mpy), 4);

                    fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4);

                }else

                    fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, 0, 4);

            }

        }

        else if(IS_16X8(mb_type)){

            for(list=0; list<h->list_count; list++){

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

                        if(IS_DIR(mb_type, i, list)){

                            int ref;

                            if(h->ref_count[list] > 1){

                                ref= decode_cabac_mb_ref( h, list, 8*i );

                                if(ref >= (unsigned)h->ref_count[list]){

                                    av_log(s->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, h->ref_count[list]);

                                    return -1;

                                }

                            }else

                                ref=0;

                            fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, ref, 1);

                        }else

                            fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, (LIST_NOT_USED&0xFF), 1);

                    }

            }

            for(list=0; list<h->list_count; list++){

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

                    if(IS_DIR(mb_type, i, list)){

                        pred_16x8_motion(h, 8*i, list, h->ref_cache[list][scan8[0] + 16*i], &mpx, &mpy);

                        mx = mpx + decode_cabac_mb_mvd( h, list, 8*i, 0 );

                        my = mpy + decode_cabac_mb_mvd( h, list, 8*i, 1 );

                        tprintf(s->avctx, "final mv:%d %d\n", mx, my);

                        fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx-mpx,my-mpy), 4);

                        fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4);

                    }else{

                        fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);

                        fill_rectangle(h-> mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);

                    }

                }

            }

        }else{

            assert(IS_8X16(mb_type));

            for(list=0; list<h->list_count; list++){

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

                        if(IS_DIR(mb_type, i, list)){ //FIXME optimize

                            int ref;

                            if(h->ref_count[list] > 1){

                                ref= decode_cabac_mb_ref( h, list, 4*i );

                                if(ref >= (unsigned)h->ref_count[list]){

                                    av_log(s->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, h->ref_count[list]);

                                    return -1;

                                }

                            }else

                                ref=0;

                            fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, ref, 1);

                        }else

                            fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, (LIST_NOT_USED&0xFF), 1);

                    }

            }

            for(list=0; list<h->list_count; list++){

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

                    if(IS_DIR(mb_type, i, list)){

                        pred_8x16_motion(h, i*4, list, h->ref_cache[list][ scan8[0] + 2*i ], &mpx, &mpy);

                        mx = mpx + decode_cabac_mb_mvd( h, list, 4*i, 0 );

                        my = mpy + decode_cabac_mb_mvd( h, list, 4*i, 1 );

                        tprintf(s->avctx, "final mv:%d %d\n", mx, my);

                        fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx-mpx,my-mpy), 4);

                        fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4);

                    }else{

                        fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4);

                        fill_rectangle(h-> mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4);

                    }

                }

            }

        }

    }

   if( IS_INTER( mb_type ) ) {

        h->chroma_pred_mode_table[mb_xy] = 0;

        write_back_motion( h, mb_type );

   }

    if( !IS_INTRA16x16( mb_type ) ) {

        cbp  = decode_cabac_mb_cbp_luma( h );

        if(CHROMA)

            cbp |= decode_cabac_mb_cbp_chroma( h ) << 4;

    }

    h->cbp_table[mb_xy] = h->cbp = cbp;

    if( dct8x8_allowed && (cbp&15) && !IS_INTRA( mb_type ) ) {

        if( decode_cabac_mb_transform_size( h ) )

            mb_type |= MB_TYPE_8x8DCT;

    }

    s->current_picture.mb_type[mb_xy]= mb_type;

    if( cbp || IS_INTRA16x16( mb_type ) ) {

        const uint8_t *scan, *scan8x8, *dc_scan;

        const uint32_t *qmul;

        int dqp;

        if(IS_INTERLACED(mb_type)){

            scan8x8= s->qscale ? h->field_scan8x8 : h->field_scan8x8_q0;

            scan= s->qscale ? h->field_scan : h->field_scan_q0;

            dc_scan= luma_dc_field_scan;

        }else{

            scan8x8= s->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0;

            scan= s->qscale ? h->zigzag_scan : h->zigzag_scan_q0;

            dc_scan= luma_dc_zigzag_scan;

        }

        h->last_qscale_diff = dqp = decode_cabac_mb_dqp( h );

        if( dqp == INT_MIN ){

            av_log(h->s.avctx, AV_LOG_ERROR, "cabac decode of qscale diff failed at %d %d\n", s->mb_x, s->mb_y);

            return -1;

        }

        s->qscale += dqp;

        if(((unsigned)s->qscale) > 51){

            if(s->qscale<0) s->qscale+= 52;

            else            s->qscale-= 52;

        }

        h->chroma_qp[0] = get_chroma_qp(h, 0, s->qscale);

        h->chroma_qp[1] = get_chroma_qp(h, 1, s->qscale);

        if( IS_INTRA16x16( mb_type ) ) {

            int i;

            //av_log( s->avctx, AV_LOG_ERROR, "INTRA16x16 DC\n" );

            decode_cabac_residual( h, h->mb, 0, 0, dc_scan, NULL, 16);

            if( cbp&15 ) {

                qmul = h->dequant4_coeff[0][s->qscale];

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

                    //av_log( s->avctx, AV_LOG_ERROR, "INTRA16x16 AC:%d\n", i );

                    decode_cabac_residual(h, h->mb + 16*i, 1, i, scan + 1, qmul, 15);

                }

            } else {

                fill_rectangle(&h->non_zero_count_cache[scan8[0]], 4, 4, 8, 0, 1);

            }

        } else {

            int i8x8, i4x4;

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

                if( cbp & (1<<i8x8) ) {

                    if( IS_8x8DCT(mb_type) ) {

                        decode_cabac_residual(h, h->mb + 64*i8x8, 5, 4*i8x8,

                            scan8x8, h->dequant8_coeff[IS_INTRA( mb_type ) ? 0:1][s->qscale], 64);

                    } else {

                        qmul = h->dequant4_coeff[IS_INTRA( mb_type ) ? 0:3][s->qscale];

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

                            const int index = 4*i8x8 + i4x4;

                            //av_log( s->avctx, AV_LOG_ERROR, "Luma4x4: %d\n", index );

//START_TIMER

                            decode_cabac_residual(h, h->mb + 16*index, 2, index, scan, qmul, 16);

//STOP_TIMER("decode_residual")

                        }

                    }

                } else {

                    uint8_t * const nnz= &h->non_zero_count_cache[ scan8[4*i8x8] ];

                    nnz[0] = nnz[1] = nnz[8] = nnz[9] = 0;

                }

            }

        }

        if( cbp&0x30 ){

            int c;

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

                //av_log( s->avctx, AV_LOG_ERROR, "INTRA C%d-DC\n",c );

                decode_cabac_residual(h, h->mb + 256 + 16*4*c, 3, c, chroma_dc_scan, NULL, 4);

            }

        }

        if( cbp&0x20 ) {

            int c, i;

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

                qmul = h->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[c]];

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

                    const int index = 16 + 4 * c + i;

                    //av_log( s->avctx, AV_LOG_ERROR, "INTRA C%d-AC %d\n",c, index - 16 );

                    decode_cabac_residual(h, h->mb + 16*index, 4, index, scan + 1, qmul, 15);

                }

            }

        } else {

            uint8_t * const nnz= &h->non_zero_count_cache[0];

            nnz[ scan8[16]+0 ] = nnz[ scan8[16]+1 ] =nnz[ scan8[16]+8 ] =nnz[ scan8[16]+9 ] =

            nnz[ scan8[20]+0 ] = nnz[ scan8[20]+1 ] =nnz[ scan8[20]+8 ] =nnz[ scan8[20]+9 ] = 0;

        }

    } else {

        uint8_t * const nnz= &h->non_zero_count_cache[0];

        fill_rectangle(&nnz[scan8[0]], 4, 4, 8, 0, 1);

        nnz[ scan8[16]+0 ] = nnz[ scan8[16]+1 ] =nnz[ scan8[16]+8 ] =nnz[ scan8[16]+9 ] =

        nnz[ scan8[20]+0 ] = nnz[ scan8[20]+1 ] =nnz[ scan8[20]+8 ] =nnz[ scan8[20]+9 ] = 0;

        h->last_qscale_diff = 0;

    }

    s->current_picture.qscale_table[mb_xy]= s->qscale;

    write_back_non_zero_count(h);

    if(MB_MBAFF){

        h->ref_count[0] >>= 1;

        h->ref_count[1] >>= 1;

    }

    return 0;

}


static int parse_read_interval(const char *interval_spec,

                               ReadInterval *interval)

{

    int ret = 0;

    char *next, *p, *spec = av_strdup(interval_spec);

    if (!spec)

        return AVERROR(ENOMEM);

    if (!*spec) {

        av_log(NULL, AV_LOG_ERROR, "Invalid empty interval specification\n");

        ret = AVERROR(EINVAL);

        goto end;

    }

    p = spec;

    next = strchr(spec, '%');

    if (next)

        *next++ = 0;

    /* parse first part */

    if (*p) {

        interval->has_start = 1;

        if (*p == '+') {

            interval->start_is_offset = 1;

            p++;

        } else {

            interval->start_is_offset = 0;

        }

        ret = av_parse_time(&interval->start, p, 1);

        if (ret < 0) {

            av_log(NULL, AV_LOG_ERROR, "Invalid interval start specification '%s'\n", p);

            goto end;

        }

    } else {

        interval->has_start = 0;

    }

    /* parse second part */

    p = next;

    if (p && *p) {

        int64_t us;

        interval->has_end = 1;

        if (*p == '+') {

            interval->end_is_offset = 1;

            p++;

        } else {

            interval->end_is_offset = 0;

        }

        if (interval->end_is_offset && *p == '#') {

            long long int lli;

            char *tail;

            interval->duration_frames = 1;

            p++;

            lli = strtoll(p, &tail, 10);

            if (*tail || lli < 0) {

                av_log(NULL, AV_LOG_ERROR,

                       "Invalid or negative value '%s' for duration number of frames\n", p);

                goto end;

            }

            interval->end = lli;

        } else {

            ret = av_parse_time(&us, p, 1);

            if (ret < 0) {

                av_log(NULL, AV_LOG_ERROR, "Invalid interval end/duration specification '%s'\n", p);

                goto end;

            }

            interval->end = us;

        }

    } else {

        interval->has_end = 0;

    }

end:

    av_free(spec);

    return ret;

}


static uint32_t qvirtio_pci_get_guest_features(QVirtioDevice *d)

{

    QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;

    return qpci_io_readl(dev->pdev, dev->addr + VIRTIO_PCI_GUEST_FEATURES);

}


bool virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)

{

    VirtIOSCSICommon *vs = &s->parent_obj;

    SCSIDevice *d;

    int rc;

    rc = virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,

                               sizeof(VirtIOSCSICmdResp) + vs->sense_size);

    if (rc < 0) {

        if (rc == -ENOTSUP) {

            virtio_scsi_fail_cmd_req(req);

        } else {

            virtio_scsi_bad_req();

        }

        return false;

    }

    d = virtio_scsi_device_find(s, req->req.cmd.lun);

    if (!d) {

        req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;

        virtio_scsi_complete_cmd_req(req);

        return false;

    }

    if (s->dataplane_started) {

        assert(blk_get_aio_context(d->conf.blk) == s->ctx);

    }

    req->sreq = scsi_req_new(d, req->req.cmd.tag,

                             virtio_scsi_get_lun(req->req.cmd.lun),

                             req->req.cmd.cdb, req);

    if (req->sreq->cmd.mode != SCSI_XFER_NONE

        && (req->sreq->cmd.mode != req->mode ||

            req->sreq->cmd.xfer > req->qsgl.size)) {

        req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN;

        virtio_scsi_complete_cmd_req(req);

        return false;

    }

    scsi_req_ref(req->sreq);

    blk_io_plug(d->conf.blk);

    return true;

}


static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid)

{

    MXFContext *mxf = arg;

    int item_num = avio_rb32(pb);

    int item_len = avio_rb32(pb);

    if (item_len != 18) {

        av_log(mxf->fc, AV_LOG_ERROR, "unsupported primer pack item length\n");

        return -1;

    }

    if (item_num > UINT_MAX / item_len)

        return -1;

    mxf->local_tags_count = item_num;

    mxf->local_tags = av_malloc(item_num*item_len);

    if (!mxf->local_tags)

        return -1;

    avio_read(pb, mxf->local_tags, item_num*item_len);

    return 0;

}


void qmp_transaction(BlockdevActionList *dev_list, Error **errp)

{

    int ret = 0;

    BlockdevActionList *dev_entry = dev_list;

    BlkTransactionStates *states, *next;

    QSIMPLEQ_HEAD(snap_bdrv_states, BlkTransactionStates) snap_bdrv_states;

    QSIMPLEQ_INIT(&snap_bdrv_states);

    /* drain all i/o before any snapshots */

    bdrv_drain_all();

    /* We don't do anything in this loop that commits us to the snapshot */

    while (NULL != dev_entry) {

        BlockdevAction *dev_info = NULL;

        BlockDriver *proto_drv;

        BlockDriver *drv;

        int flags;

        enum NewImageMode mode;

        const char *new_image_file;

        const char *device;

        const char *format = "qcow2";

        dev_info = dev_entry->value;

        dev_entry = dev_entry->next;

        states = g_malloc0(sizeof(BlkTransactionStates));

        QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry);

        switch (dev_info->kind) {

        case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:

            device = dev_info->blockdev_snapshot_sync->device;

            if (!dev_info->blockdev_snapshot_sync->has_mode) {

                dev_info->blockdev_snapshot_sync->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;

            }

            new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file;

            if (dev_info->blockdev_snapshot_sync->has_format) {

                format = dev_info->blockdev_snapshot_sync->format;

            }

            mode = dev_info->blockdev_snapshot_sync->mode;

            break;

        default:

            abort();

        }

        drv = bdrv_find_format(format);

        if (!drv) {

            error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);

            goto delete_and_fail;

        }

        states->old_bs = bdrv_find(device);

        if (!states->old_bs) {

            error_set(errp, QERR_DEVICE_NOT_FOUND, device);

            goto delete_and_fail;

        }

        if (!bdrv_is_inserted(states->old_bs)) {

            error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);

            goto delete_and_fail;

        }

        if (bdrv_in_use(states->old_bs)) {

            error_set(errp, QERR_DEVICE_IN_USE, device);

            goto delete_and_fail;

        }

        if (!bdrv_is_read_only(states->old_bs)) {

            if (bdrv_flush(states->old_bs)) {

                error_set(errp, QERR_IO_ERROR);

                goto delete_and_fail;

            }

        }

        flags = states->old_bs->open_flags;

        proto_drv = bdrv_find_protocol(new_image_file);

        if (!proto_drv) {

            error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);

            goto delete_and_fail;

        }

        /* create new image w/backing file */

        if (mode != NEW_IMAGE_MODE_EXISTING) {

            ret = bdrv_img_create(new_image_file, format,

                                  states->old_bs->filename,

                                  states->old_bs->drv->format_name,

                                  NULL, -1, flags);

            if (ret) {

                error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);

                goto delete_and_fail;

            }

        }

        /* We will manually add the backing_hd field to the bs later */

        states->new_bs = bdrv_new("");

        ret = bdrv_open(states->new_bs, new_image_file,

                        flags | BDRV_O_NO_BACKING, drv);

        if (ret != 0) {

            error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);

            goto delete_and_fail;

        }

    }

    /* Now we are going to do the actual pivot.  Everything up to this point

     * is reversible, but we are committed at this point */

    QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {

        /* This removes our old bs from the bdrv_states, and adds the new bs */

        bdrv_append(states->new_bs, states->old_bs);

    }

    /* success */

    goto exit;

delete_and_fail:

    /*

    * failure, and it is all-or-none; abandon each new bs, and keep using

    * the original bs for all images

    */

    QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) {

        if (states->new_bs) {

             bdrv_delete(states->new_bs);

        }

    }

exit:

    QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) {

        g_free(states);

    }

    return;

}


static int genh_read_header(AVFormatContext *s)

{

    unsigned start_offset, header_size, codec, coef_type, coef[2];

    GENHDemuxContext *c = s->priv_data;

    av_unused unsigned coef_splitted[2];

    int align, ch, ret;

    AVStream *st;

    avio_skip(s->pb, 4);

    st = avformat_new_stream(s, NULL);

    if (!st)

        return AVERROR(ENOMEM);

    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;

    st->codecpar->channels    = avio_rl32(s->pb);

    if (st->codecpar->channels <= 0)

        return AVERROR_INVALIDDATA;

    if (st->codecpar->channels == 1)

        st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;

    else if (st->codecpar->channels == 2)

        st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;

    align                  =

    c->interleave_size     = avio_rl32(s->pb);

    if (align < 0 || align > INT_MAX / st->codecpar->channels)

        return AVERROR_INVALIDDATA;

    st->codecpar->block_align = align * st->codecpar->channels;

    st->codecpar->sample_rate = avio_rl32(s->pb);

    avio_skip(s->pb, 4);

    st->duration = avio_rl32(s->pb);

    codec = avio_rl32(s->pb);

    switch (codec) {

    case  0: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX;        break;

    case  1:

    case 11: st->codecpar->bits_per_coded_sample = 4;

             st->codecpar->block_align = 36 * st->codecpar->channels;

             st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WAV;    break;

    case  2: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_DTK;        break;

    case  3: st->codecpar->codec_id = st->codecpar->block_align > 0 ?

                                   AV_CODEC_ID_PCM_S16BE_PLANAR :

                                   AV_CODEC_ID_PCM_S16BE;        break;

    case  4: st->codecpar->codec_id = st->codecpar->block_align > 0 ?

                                   AV_CODEC_ID_PCM_S16LE_PLANAR :

                                   AV_CODEC_ID_PCM_S16LE;        break;

    case  5: st->codecpar->codec_id = st->codecpar->block_align > 0 ?

                                   AV_CODEC_ID_PCM_S8_PLANAR :

                                   AV_CODEC_ID_PCM_S8;           break;

    case  6: st->codecpar->codec_id = AV_CODEC_ID_SDX2_DPCM;        break;

    case  7: ret = ff_alloc_extradata(st->codecpar, 2);

             if (ret < 0)

                 return ret;

             AV_WL16(st->codecpar->extradata, 3);

             st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;     break;

    case 10: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AICA;       break;

    case 12: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_THP;        break;

    case 13: st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;           break;

    case 17: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_QT;     break;

    default:

             avpriv_request_sample(s, "codec %d", codec);

             return AVERROR_PATCHWELCOME;

    }

    start_offset = avio_rl32(s->pb);

    header_size  = avio_rl32(s->pb);

    if (header_size > start_offset)

        return AVERROR_INVALIDDATA;

    if (header_size == 0)

        start_offset = 0x800;

    coef[0]          = avio_rl32(s->pb);

    coef[1]          = avio_rl32(s->pb);

    c->dsp_int_type  = avio_rl32(s->pb);

    coef_type        = avio_rl32(s->pb);

    coef_splitted[0] = avio_rl32(s->pb);

    coef_splitted[1] = avio_rl32(s->pb);

    if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_THP) {

        if (st->codecpar->channels > 2) {

            avpriv_request_sample(s, "channels %d>2", st->codecpar->channels);

            return AVERROR_PATCHWELCOME;

        }

        ff_alloc_extradata(st->codecpar, 32 * st->codecpar->channels);

        for (ch = 0; ch < st->codecpar->channels; ch++) {

            if (coef_type & 1) {

                avpriv_request_sample(s, "coef_type & 1");

                return AVERROR_PATCHWELCOME;

            } else {

                avio_seek(s->pb, coef[ch], SEEK_SET);

                avio_read(s->pb, st->codecpar->extradata + 32 * ch, 32);

            }

        }

        if (c->dsp_int_type == 1) {

            st->codecpar->block_align = 8 * st->codecpar->channels;

            if (c->interleave_size != 1 &&

                c->interleave_size != 2 &&

                c->interleave_size != 4)

                return AVERROR_INVALIDDATA;

        }

    }

    avio_skip(s->pb, start_offset - avio_tell(s->pb));

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

    return 0;

}


static void virtio_scsi_class_init(ObjectClass *klass, void *data)

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);

    dc->exit = virtio_scsi_device_exit;

    dc->props = virtio_scsi_properties;

    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);

    vdc->init = virtio_scsi_device_init;

    vdc->set_config = virtio_scsi_set_config;

    vdc->get_features = virtio_scsi_get_features;

    vdc->reset = virtio_scsi_reset;

}


static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,

                                  Jpeg2000CodingStyle *codsty,

                                  Jpeg2000ResLevel *rlevel, int precno,

                                  int layno, uint8_t *expn, int numgbits)

{

    int bandno, cblkno, ret, nb_code_blocks;

    if (!(ret = get_bits(s, 1))) {

        jpeg2000_flush(s);

        return 0;

    } else if (ret < 0)

        return ret;

    for (bandno = 0; bandno < rlevel->nbands; bandno++) {

        Jpeg2000Band *band = rlevel->band + bandno;

        Jpeg2000Prec *prec = band->prec + precno;

        if (band->coord[0][0] == band->coord[0][1] ||

            band->coord[1][0] == band->coord[1][1])

            continue;

        nb_code_blocks =  prec->nb_codeblocks_height *

                          prec->nb_codeblocks_width;

        for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {

            Jpeg2000Cblk *cblk = prec->cblk + cblkno;

            int incl, newpasses, llen;

            if (cblk->npasses)

                incl = get_bits(s, 1);

            else

                incl = tag_tree_decode(s, prec->cblkincl + cblkno, layno + 1) == layno;

            if (!incl)

                continue;

            else if (incl < 0)

                return incl;

            if (!cblk->npasses)

                cblk->nonzerobits = expn[bandno] + numgbits - 1 -

                                    tag_tree_decode(s, prec->zerobits + cblkno,

                                                    100);

            if ((newpasses = getnpasses(s)) < 0)

                return newpasses;

            if ((llen = getlblockinc(s)) < 0)

                return llen;

            cblk->lblock += llen;

            if ((ret = get_bits(s, av_log2(newpasses) + cblk->lblock)) < 0)

                return ret;

            cblk->lengthinc = ret;

            cblk->npasses  += newpasses;

        }

    }

    jpeg2000_flush(s);

    if (codsty->csty & JPEG2000_CSTY_EPH) {

        if (bytestream2_peek_be16(&s->g) == JPEG2000_EPH)

            bytestream2_skip(&s->g, 2);

        else

            av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found.\n");

    }

    for (bandno = 0; bandno < rlevel->nbands; bandno++) {

        Jpeg2000Band *band = rlevel->band + bandno;

        Jpeg2000Prec *prec = band->prec + precno;

        nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width;

        for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {

            Jpeg2000Cblk *cblk = prec->cblk + cblkno;

            if (   bytestream2_get_bytes_left(&s->g) < cblk->lengthinc

                || sizeof(cblk->data) < cblk->lengthinc

            )

                return AVERROR(EINVAL);

            /* Code-block data can be empty. In that case initialize data

             * with 0xFFFF. */

            if (cblk->lengthinc > 0) {

                bytestream2_get_bufferu(&s->g, cblk->data, cblk->lengthinc);

            } else {

                cblk->data[0] = 0xFF;

                cblk->data[1] = 0xFF;

            }

            cblk->length   += cblk->lengthinc;

            cblk->lengthinc = 0;

        }

    }

    return 0;

}


void v9fs_device_unrealize_common(V9fsState *s, Error **errp)

{

    g_free(s->tag);

    g_free(s->ctx.fs_root);


void virtio_scsi_common_realize(DeviceState *dev, Error **errp,

                                HandleOutput ctrl, HandleOutput evt,

                                HandleOutput cmd)

{

    VirtIODevice *vdev = VIRTIO_DEVICE(dev);

    VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);

    int i;

    virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,

                sizeof(VirtIOSCSIConfig));

    if (s->conf.num_queues <= 0 || s->conf.num_queues > VIRTIO_PCI_QUEUE_MAX) {

        error_setg(errp, "Invalid number of queues (= %" PRId32 "), "

                         "must be a positive integer less than %d.",

                   s->conf.num_queues, VIRTIO_PCI_QUEUE_MAX);

        return;

    }

    s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));

    s->sense_size = VIRTIO_SCSI_SENSE_SIZE;

    s->cdb_size = VIRTIO_SCSI_CDB_SIZE;

    s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,

                                  ctrl);

    s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,

                                   evt);

    for (i = 0; i < s->conf.num_queues; i++) {

        s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,

                                         cmd);

    }

    if (s->conf.iothread) {

        virtio_scsi_set_iothread(VIRTIO_SCSI(s), s->conf.iothread);

    }

}


static int rpza_decode_frame(AVCodecContext *avctx,

                             void *data, int *got_frame,

                             AVPacket *avpkt)

{

    RpzaContext *s = avctx->priv_data;

    int ret;

    bytestream2_init(&s->gb, avpkt->data, avpkt->size);

    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) {

        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");

        return ret;

    }

    rpza_decode_stream(s);

    if ((ret = av_frame_ref(data, s->frame)) < 0)

        return ret;

    *got_frame      = 1;

    /* always report that the buffer was completely consumed */

    return avpkt->size;

}


static int decode_cell_data(Cell *cell, uint8_t *block, uint8_t *ref_block,
                            int pitch, int h_zoom, int v_zoom, int mode,
                            const vqEntry *delta[2], int swap_quads[2],
                            const uint8_t **data_ptr, const uint8_t *last_ptr)
{
    int           x, y, line, num_lines;
    int           rle_blocks = 0;
    uint8_t       code, *dst, *ref;
    const vqEntry *delta_tab;
    unsigned int  dyad1, dyad2;
    uint64_t      pix64;
    int           skip_flag = 0, is_top_of_cell, is_first_row = 1;
    int           row_offset, blk_row_offset, line_offset;
    row_offset     =  pitch;
    blk_row_offset = (row_offset << (2 + v_zoom)) - (cell->width << 2);
    line_offset    = v_zoom ? row_offset : 0;
    for (y = 0; y < cell->height; is_first_row = 0, y += 1 + v_zoom) {
        for (x = 0; x < cell->width; x += 1 + h_zoom) {
            ref = ref_block;
            dst = block;
            if (rle_blocks > 0) {
                if (mode <= 4) {
                    RLE_BLOCK_COPY;
                } else if (mode == 10 && !cell->mv_ptr) {
                    RLE_BLOCK_COPY_8;
                }
                rle_blocks--;
            } else {
                for (line = 0; line < 4;) {
                    num_lines = 1;
                    is_top_of_cell = is_first_row && !line;
                    /* select primary VQ table for odd, secondary for even lines */
                    if (mode <= 4)
                        delta_tab = delta[line & 1];
                    else
                        delta_tab = delta[1];
                    BUFFER_PRECHECK;
                    code = bytestream_get_byte(data_ptr);
                    if (code < 248) {
                        if (code < delta_tab->num_dyads) {
                            BUFFER_PRECHECK;
                            dyad1 = bytestream_get_byte(data_ptr);
                            dyad2 = code;
                            if (dyad1 >= delta_tab->num_dyads || dyad1 >= 248)
                        } else {
                            /* process QUADS */
                            code -= delta_tab->num_dyads;
                            dyad1 = code / delta_tab->quad_exp;
                            dyad2 = code % delta_tab->quad_exp;
                            if (swap_quads[line & 1])
                                FFSWAP(unsigned int, dyad1, dyad2);
                        }
                        if (mode <= 4) {
                            APPLY_DELTA_4;
                        } else if (mode == 10 && !cell->mv_ptr) {
                            APPLY_DELTA_8;
                        } else {
                            APPLY_DELTA_1011_INTER;
                        }
                    } else {
                        /* process RLE codes */
                        switch (code) {
                        case RLE_ESC_FC:
                            skip_flag  = 0;
                            rle_blocks = 1;
                            code       = 253;
                            /* FALLTHROUGH */
                        case RLE_ESC_FF:
                        case RLE_ESC_FE:
                        case RLE_ESC_FD:
                            num_lines = 257 - code - line;
                            if (num_lines <= 0)
                                return IV3_BAD_RLE;
                            if (mode <= 4) {
                                RLE_LINES_COPY;
                            } else if (mode == 10 && !cell->mv_ptr) {
                                RLE_LINES_COPY_M10;
                            }
                            break;
                        case RLE_ESC_FB:
                            BUFFER_PRECHECK;
                            code = bytestream_get_byte(data_ptr);
                            rle_blocks = (code & 0x1F) - 1; /* set block counter */
                            if (code >= 64 || rle_blocks < 0)
                                return IV3_BAD_COUNTER;
                            skip_flag = code & 0x20;
                            num_lines = 4 - line; /* enforce next block processing */
                            if (mode >= 10 || (cell->mv_ptr || !skip_flag)) {
                                if (mode <= 4) {
                                    RLE_LINES_COPY;
                                } else if (mode == 10 && !cell->mv_ptr) {
                                    RLE_LINES_COPY_M10;
                                }
                            }
                            break;
                        case RLE_ESC_F9:
                            skip_flag  = 1;
                            rle_blocks = 1;
                            /* FALLTHROUGH */
                        case RLE_ESC_FA:
                            if (line)
                                return IV3_BAD_RLE;
                            num_lines = 4; /* enforce next block processing */
                            if (cell->mv_ptr) {
                                if (mode <= 4) {
                                    RLE_LINES_COPY;
                                } else if (mode == 10 && !cell->mv_ptr) {
                                    RLE_LINES_COPY_M10;
                                }
                            }
                            break;
                        default:
                            return IV3_UNSUPPORTED;
                        }
                    }
                    line += num_lines;
                    ref  += row_offset * (num_lines << v_zoom);
                    dst  += row_offset * (num_lines << v_zoom);
                }
            }
            /* move to next horizontal block */
            block     += 4 << h_zoom;
            ref_block += 4 << h_zoom;
        }
        /* move to next line of blocks */
        ref_block += blk_row_offset;
        block     += blk_row_offset;
    }
    return IV3_NOERR;
}


static void superh_cpu_realizefn(DeviceState *dev, Error **errp)

{

    SuperHCPU *cpu = SUPERH_CPU(dev);

    SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(dev);

    cpu_reset(CPU(cpu));

    scc->parent_realize(dev, errp);

}


static void http_log(char *fmt, ...)

{

    va_list ap;

    va_start(ap, fmt);

    if (logfile)

        vfprintf(logfile, fmt, ap);

    va_end(ap);

}


void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip)

{

    const ARMCPRegInfo *ri = rip;

    switch (ri->accessfn(env, ri)) {

    case CP_ACCESS_OK:

        return;

    case CP_ACCESS_TRAP:

    case CP_ACCESS_TRAP_UNCATEGORIZED:

        /* These cases will eventually need to generate different

         * syndrome information.

         */

        break;

    default:

        g_assert_not_reached();

    }

    raise_exception(env, EXCP_UDEF);

}


static void skip_block (uint8_t *current, uint8_t *previous, int pitch, int x, int y) {

  uint8_t *src;

  uint8_t *dst;

  int	   i;

  src = &previous[x + y*pitch];

  dst = current;

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

    memcpy (dst, src, 16);

    src += pitch;

    dst += pitch;

  }

}


static int mlp_parse(AVCodecParserContext *s,

                     AVCodecContext *avctx,

                     const uint8_t **poutbuf, int *poutbuf_size,

                     const uint8_t *buf, int buf_size)

{

    MLPParseContext *mp = s->priv_data;

    int sync_present;

    uint8_t parity_bits;

    int next;

    int i, p = 0;

    *poutbuf_size = 0;

    if (buf_size == 0)

        return 0;

    if (!mp->in_sync) {

        // Not in sync - find a major sync header

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

            mp->pc.state = (mp->pc.state << 8) | buf[i];

            if ((mp->pc.state & 0xfffffffe) == 0xf8726fba &&

                // ignore if we do not have the data for the start of header

                mp->pc.index + i >= 7) {

                mp->in_sync = 1;

                mp->bytes_left = 0;

                break;

            }

        }

        if (!mp->in_sync) {

            ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);

            return buf_size;

        }

        ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size);

        return i - 7;

    }

    if (mp->bytes_left == 0) {

        // Find length of this packet

        /* Copy overread bytes from last frame into buffer. */

        for(; mp->pc.overread>0; mp->pc.overread--) {

            mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++];

        }

        if (mp->pc.index + buf_size < 2) {

            ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);

            return buf_size;

        }

        mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8)

                       |  (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]);

        mp->bytes_left = (mp->bytes_left & 0xfff) * 2;

        if (mp->bytes_left <= 0) { // prevent infinite loop

            goto lost_sync;

        }

        mp->bytes_left -= mp->pc.index;

    }

    next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left;

    if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) {

        mp->bytes_left -= buf_size;

        return buf_size;

    }

    mp->bytes_left = 0;

    sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba;

    if (!sync_present) {

        /* The first nibble of a frame is a parity check of the 4-byte

         * access unit header and all the 2- or 4-byte substream headers. */

        // Only check when this isn't a sync frame - syncs have a checksum.

        parity_bits = 0;

        for (i = -1; i < mp->num_substreams; i++) {

            parity_bits ^= buf[p++];

            parity_bits ^= buf[p++];

            if (i < 0 || buf[p-2] & 0x80) {

                parity_bits ^= buf[p++];

                parity_bits ^= buf[p++];

            }

        }

        if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) {

            av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n");

            goto lost_sync;

        }

    } else {

        GetBitContext gb;

        MLPHeaderInfo mh;

        init_get_bits(&gb, buf + 4, (buf_size - 4) << 3);

        if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0)

            goto lost_sync;

        avctx->bits_per_raw_sample = mh.group1_bits;

        if (avctx->bits_per_raw_sample > 16)

            avctx->sample_fmt = AV_SAMPLE_FMT_S32;

        else

            avctx->sample_fmt = AV_SAMPLE_FMT_S16;

        avctx->sample_rate = mh.group1_samplerate;

        s->duration = mh.access_unit_size;

        if (mh.stream_type == 0xbb) {

            /* MLP stream */

            avctx->channels = mlp_channels[mh.channels_mlp];

            avctx->channel_layout = ff_mlp_layout[mh.channels_mlp];

        } else { /* mh.stream_type == 0xba */

            /* TrueHD stream */

            if (mh.channels_thd_stream2) {

                avctx->channels = truehd_channels(mh.channels_thd_stream2);

                avctx->channel_layout = ff_truehd_layout(mh.channels_thd_stream2);

            } else {

                avctx->channels = truehd_channels(mh.channels_thd_stream1);

                avctx->channel_layout = ff_truehd_layout(mh.channels_thd_stream1);

            }

        }

        }

        if (!mh.is_vbr) /* Stream is CBR */

            avctx->bit_rate = mh.peak_bitrate;

        mp->num_substreams = mh.num_substreams;

    }

    *poutbuf = buf;

    *poutbuf_size = buf_size;

    return next;

lost_sync:

    mp->in_sync = 0;

    return 1;

}


void ppc_translate_init(void)
{
    int i;
    char* p;
    size_t cpu_reg_names_size;
    static int done_init = 0;
    if (done_init)
        return;
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
    p = cpu_reg_names;
    cpu_reg_names_size = sizeof(cpu_reg_names);
    for (i = 0; i < 8; i++) {
        snprintf(p, cpu_reg_names_size, "crf%d", i);
        cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                            offsetof(CPUState, crf[i]), p);
        p += 5;
        cpu_reg_names_size -= 5;
    }
    for (i = 0; i < 32; i++) {
        snprintf(p, cpu_reg_names_size, "r%d", i);
        cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
                                        offsetof(CPUState, gpr[i]), p);
        p += (i < 10) ? 3 : 4;
        cpu_reg_names_size -= (i < 10) ? 3 : 4;
#if !defined(TARGET_PPC64)
        snprintf(p, cpu_reg_names_size, "r%dH", i);
        cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
                                             offsetof(CPUState, gprh[i]), p);
        p += (i < 10) ? 4 : 5;
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
        snprintf(p, cpu_reg_names_size, "fp%d", i);
        cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                            offsetof(CPUState, fpr[i]), p);
        p += (i < 10) ? 4 : 5;
        cpu_reg_names_size -= (i < 10) ? 4 : 5;
        snprintf(p, cpu_reg_names_size, "avr%dH", i);
#ifdef HOST_WORDS_BIGENDIAN
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                             offsetof(CPUState, avr[i].u64[0]), p);
#else
        cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                             offsetof(CPUState, avr[i].u64[1]), p);
        p += (i < 10) ? 6 : 7;
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
        snprintf(p, cpu_reg_names_size, "avr%dL", i);
#ifdef HOST_WORDS_BIGENDIAN
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                             offsetof(CPUState, avr[i].u64[1]), p);
#else
        cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                             offsetof(CPUState, avr[i].u64[0]), p);
        p += (i < 10) ? 6 : 7;
        cpu_reg_names_size -= (i < 10) ? 6 : 7;
    }
    cpu_nip = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUState, nip), "nip");
    cpu_msr = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUState, msr), "msr");
    cpu_ctr = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUState, ctr), "ctr");
    cpu_lr = tcg_global_mem_new(TCG_AREG0,
                                offsetof(CPUState, lr), "lr");
    cpu_xer = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUState, xer), "xer");
    cpu_reserve = tcg_global_mem_new(TCG_AREG0,
                                     offsetof(CPUState, reserve_addr),
                                     "reserve_addr");
    cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
                                       offsetof(CPUState, fpscr), "fpscr");
    cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
                                             offsetof(CPUState, access_type), "access_type");
    /* register helpers */
#define GEN_HELPER 2
#include "helper.h"
    done_init = 1;
}


void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar)

{

    hc->dev = qpci_device_find(pcibus, devfn);

    g_assert(hc->dev != NULL);

    qpci_device_enable(hc->dev);

    hc->base = qpci_iomap(hc->dev, bar, NULL);

    g_assert(hc->base != NULL);

}


static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)

{

    const char *hdlr, *descr = NULL, *hdlr_type = NULL;

    int64_t pos = avio_tell(pb);

    if (!track) { /* no media --> data handler */

        hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";

        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {

            hdlr_type = "vide";

            descr = "VideoHandler";

        } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {

            hdlr_type = "soun";

            descr = "SoundHandler";

        } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {

            if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl";

            else                                      hdlr_type = "text";

            descr = "SubtitleHandler";

        } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {

            hdlr_type = "hint";

            descr = "HintHandler";

        }

    }

    avio_wb32(pb, 0); /* size */

    ffio_wfourcc(pb, "hdlr");

    avio_wb32(pb, 0); /* Version & flags */

    avio_write(pb, hdlr, 4); /* handler */

    ffio_wfourcc(pb, hdlr_type); /* handler type */

    avio_wb32(pb ,0); /* reserved */

    avio_wb32(pb ,0); /* reserved */

    avio_wb32(pb ,0); /* reserved */

    if (!track || track->mode == MODE_MOV)

        avio_w8(pb, strlen(descr)); /* pascal string */

    avio_write(pb, descr, strlen(descr)); /* handler description */

    if (track && track->mode != MODE_MOV)

        avio_w8(pb, 0); /* c string */

    return update_size(pb, pos);

}


static coroutine_fn void nbd_co_client_start(void *opaque)

{

    NBDClientNewData *data = opaque;

    NBDClient *client = data->client;

    NBDExport *exp = client->exp;

    if (exp) {

        nbd_export_get(exp);

        QTAILQ_INSERT_TAIL(&exp->clients, client, next);

    }

    qemu_co_mutex_init(&client->send_lock);

    if (nbd_negotiate(data)) {

        client_close(client);

        goto out;

    }

    nbd_client_receive_next_request(client);

out:

    g_free(data);

}


static inline int vfp_exceptbits_from_host(int host_bits)

{

    int target_bits = 0;

    if (host_bits & float_flag_invalid)

        target_bits |= 1;

    if (host_bits & float_flag_divbyzero)

        target_bits |= 2;

    if (host_bits & float_flag_overflow)

        target_bits |= 4;

    if (host_bits & float_flag_underflow)

        target_bits |= 8;

    if (host_bits & float_flag_inexact)

        target_bits |= 0x10;

    if (host_bits & float_flag_input_denormal)

        target_bits |= 0x80;

    return target_bits;

}


const char *memory_region_name(const MemoryRegion *mr)

{

    return object_get_canonical_path_component(OBJECT(mr));

}


static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row,

                                   AVFrame *frame, int x, int y)

{

    int shift1 = ctx->bit_depth == 10;

    int dct_linesize_luma   = frame->linesize[0];

    int dct_linesize_chroma = frame->linesize[1];

    uint8_t *dest_y, *dest_u, *dest_v;

    int dct_y_offset, dct_x_offset;

    int qscale, i, act;

    int interlaced_mb = 0;

    if (ctx->mbaff) {

        interlaced_mb = get_bits1(&row->gb);

        qscale = get_bits(&row->gb, 10);

    } else

        qscale = get_bits(&row->gb, 11);

    act = get_bits1(&row->gb);

    if (act) {

        static int warned = 0;

        if (!warned) {

            warned = 1;

            av_log(ctx->avctx, AV_LOG_ERROR,

                   "Unsupported adaptive color transform, patch welcome.\n");

        }

    }

    if (qscale != row->last_qscale) {

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

            row->luma_scale[i]   = qscale * ctx->cid_table->luma_weight[i];

            row->chroma_scale[i] = qscale * ctx->cid_table->chroma_weight[i];

        }

        row->last_qscale = qscale;

    }

    for (i = 0; i < 8 + 4 * ctx->is_444; i++) {

        ctx->decode_dct_block(ctx, row, i);

    }

    if (frame->interlaced_frame) {

        dct_linesize_luma   <<= 1;

        dct_linesize_chroma <<= 1;

    }

    dest_y = frame->data[0] + ((y * dct_linesize_luma)   << 4) + (x << (4 + shift1));

    dest_u = frame->data[1] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1 + ctx->is_444));

    dest_v = frame->data[2] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1 + ctx->is_444));

    if (frame->interlaced_frame && ctx->cur_field) {

        dest_y += frame->linesize[0];

        dest_u += frame->linesize[1];

        dest_v += frame->linesize[2];

    }

    if (interlaced_mb) {

        dct_linesize_luma   <<= 1;

        dct_linesize_chroma <<= 1;

    }

    dct_y_offset = interlaced_mb ? frame->linesize[0] : (dct_linesize_luma << 3);

    dct_x_offset = 8 << shift1;

    if (!ctx->is_444) {

        ctx->idsp.idct_put(dest_y,                               dct_linesize_luma, row->blocks[0]);

        ctx->idsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, row->blocks[1]);

        ctx->idsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, row->blocks[4]);

        ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, row->blocks[5]);

        if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) {

            dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3);

            ctx->idsp.idct_put(dest_u,                dct_linesize_chroma, row->blocks[2]);

            ctx->idsp.idct_put(dest_v,                dct_linesize_chroma, row->blocks[3]);

            ctx->idsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, row->blocks[6]);

            ctx->idsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, row->blocks[7]);

        }

    } else {

        ctx->idsp.idct_put(dest_y,                               dct_linesize_luma, row->blocks[0]);

        ctx->idsp.idct_put(dest_y + dct_x_offset,                dct_linesize_luma, row->blocks[1]);

        ctx->idsp.idct_put(dest_y + dct_y_offset,                dct_linesize_luma, row->blocks[6]);

        ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, row->blocks[7]);

        if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) {

            dct_y_offset = interlaced_mb ? frame->linesize[1] : (dct_linesize_chroma << 3);

            ctx->idsp.idct_put(dest_u,                               dct_linesize_chroma, row->blocks[2]);

            ctx->idsp.idct_put(dest_u + dct_x_offset,                dct_linesize_chroma, row->blocks[3]);

            ctx->idsp.idct_put(dest_u + dct_y_offset,                dct_linesize_chroma, row->blocks[8]);

            ctx->idsp.idct_put(dest_u + dct_y_offset + dct_x_offset, dct_linesize_chroma, row->blocks[9]);

            ctx->idsp.idct_put(dest_v,                               dct_linesize_chroma, row->blocks[4]);

            ctx->idsp.idct_put(dest_v + dct_x_offset,                dct_linesize_chroma, row->blocks[5]);

            ctx->idsp.idct_put(dest_v + dct_y_offset,                dct_linesize_chroma, row->blocks[10]);

            ctx->idsp.idct_put(dest_v + dct_y_offset + dct_x_offset, dct_linesize_chroma, row->blocks[11]);

        }

    }

    return 0;

}


static void bonito_writel(void *opaque, hwaddr addr,

                          uint64_t val, unsigned size)

{

    PCIBonitoState *s = opaque;

    uint32_t saddr;

    int reset = 0;

    saddr = (addr - BONITO_REGBASE) >> 2;

    DPRINTF("bonito_writel "TARGET_FMT_plx" val %x saddr %x\n", addr, val, saddr);

    switch (saddr) {

    case BONITO_BONPONCFG:

    case BONITO_IODEVCFG:

    case BONITO_SDCFG:

    case BONITO_PCIMAP:

    case BONITO_PCIMEMBASECFG:

    case BONITO_PCIMAP_CFG:

    case BONITO_GPIODATA:

    case BONITO_GPIOIE:

    case BONITO_INTEDGE:

    case BONITO_INTSTEER:

    case BONITO_INTPOL:

    case BONITO_PCIMAIL0:

    case BONITO_PCIMAIL1:

    case BONITO_PCIMAIL2:

    case BONITO_PCIMAIL3:

    case BONITO_PCICACHECTRL:

    case BONITO_PCICACHETAG:

    case BONITO_PCIBADADDR:

    case BONITO_PCIMSTAT:

    case BONITO_TIMECFG:

    case BONITO_CPUCFG:

    case BONITO_DQCFG:

    case BONITO_MEMSIZE:

        s->regs[saddr] = val;

        break;

    case BONITO_BONGENCFG:

        if (!(s->regs[saddr] & 0x04) && (val & 0x04)) {

            reset = 1; /* bit 2 jump from 0 to 1 cause reset */

        }

        s->regs[saddr] = val;

        if (reset) {

            qemu_system_reset_request();

        }

        break;

    case BONITO_INTENSET:

        s->regs[BONITO_INTENSET] = val;

        s->regs[BONITO_INTEN] |= val;

        break;

    case BONITO_INTENCLR:

        s->regs[BONITO_INTENCLR] = val;

        s->regs[BONITO_INTEN] &= ~val;

        break;

    case BONITO_INTEN:

    case BONITO_INTISR:

        DPRINTF("write to readonly bonito register %x\n", saddr);

        break;

    default:

        DPRINTF("write to unknown bonito register %x\n", saddr);

        break;

    }

}


static int init_resampler(AVCodecContext *input_codec_context,

                          AVCodecContext *output_codec_context,

                          SwrContext **resample_context)

{

    /**

     * Only initialize the resampler if it is necessary, i.e.,

     * if and only if the sample formats differ.

     */

    if (input_codec_context->sample_fmt != output_codec_context->sample_fmt ||

        input_codec_context->channels != output_codec_context->channels) {

        int error;

        /**

         * Create a resampler context for the conversion.

         * Set the conversion parameters.

         * Default channel layouts based on the number of channels

         * are assumed for simplicity (they are sometimes not detected

         * properly by the demuxer and/or decoder).

         */

        *resample_context = swr_alloc_set_opts(NULL,

                                              av_get_default_channel_layout(output_codec_context->channels),

                                              output_codec_context->sample_fmt,

                                              output_codec_context->sample_rate,

                                              av_get_default_channel_layout(input_codec_context->channels),

                                              input_codec_context->sample_fmt,

                                              input_codec_context->sample_rate,

                                              0, NULL);

        if (!*resample_context) {

            fprintf(stderr, "Could not allocate resample context\n");

            return AVERROR(ENOMEM);

        }

        /**

        * Perform a sanity check so that the number of converted samples is

        * not greater than the number of samples to be converted.

        * If the sample rates differ, this case has to be handled differently

        */

        av_assert0(output_codec_context->sample_rate == input_codec_context->sample_rate);

        /** Open the resampler with the specified parameters. */

        if ((error = swr_init(*resample_context)) < 0) {

            fprintf(stderr, "Could not open resample context\n");

            swr_free(resample_context);

            return error;

        }

    }

    return 0;

}


static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)

{

    int ret = -EINVAL, idx;

    struct rdma_cm_id *listen_id;

    char ip[40] = "unknown";

    struct addrinfo *res;

    char port_str[16];

    for (idx = 0; idx < RDMA_WRID_MAX; idx++) {

        rdma->wr_data[idx].control_len = 0;

        rdma->wr_data[idx].control_curr = NULL;

    }

    if (rdma->host == NULL) {

        ERROR(errp, "RDMA host is not set!");

        rdma->error_state = -EINVAL;

        return -1;

    }

    /* create CM channel */

    rdma->channel = rdma_create_event_channel();

    if (!rdma->channel) {

        ERROR(errp, "could not create rdma event channel");

        rdma->error_state = -EINVAL;

        return -1;

    }

    /* create CM id */

    ret = rdma_create_id(rdma->channel, &listen_id, NULL, RDMA_PS_TCP);

    if (ret) {

        ERROR(errp, "could not create cm_id!");

        goto err_dest_init_create_listen_id;

    }

    snprintf(port_str, 16, "%d", rdma->port);

    port_str[15] = '\0';

    if (rdma->host && strcmp("", rdma->host)) {

        struct addrinfo *e;

        ret = getaddrinfo(rdma->host, port_str, NULL, &res);

        if (ret < 0) {

            ERROR(errp, "could not getaddrinfo address %s", rdma->host);

            goto err_dest_init_bind_addr;

        }

        for (e = res; e != NULL; e = e->ai_next) {

            inet_ntop(e->ai_family,

                &((struct sockaddr_in *) e->ai_addr)->sin_addr, ip, sizeof ip);

            DPRINTF("Trying %s => %s\n", rdma->host, ip);

            ret = rdma_bind_addr(listen_id, e->ai_addr);

            if (!ret) {

                goto listen;

            }

        }

        ERROR(errp, "Error: could not rdma_bind_addr!");

        goto err_dest_init_bind_addr;

    } else {

        ERROR(errp, "migration host and port not specified!");

        ret = -EINVAL;

        goto err_dest_init_bind_addr;

    }

listen:

    rdma->listen_id = listen_id;

    qemu_rdma_dump_gid("dest_init", listen_id);

    return 0;

err_dest_init_bind_addr:

    rdma_destroy_id(listen_id);

err_dest_init_create_listen_id:

    rdma_destroy_event_channel(rdma->channel);

    rdma->channel = NULL;

    rdma->error_state = ret;

    return ret;

}


static int msmpeg4v12_decode_mb(MpegEncContext *s, int16_t block[6][64])

{

    int cbp, code, i;

    uint32_t * const mb_type_ptr = &s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride];

    if (s->pict_type == AV_PICTURE_TYPE_P) {

        if (s->use_skip_mb_code) {

            if (get_bits1(&s->gb)) {

                /* skip mb */

                s->mb_intra = 0;

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

                    s->block_last_index[i] = -1;

                s->mv_dir = MV_DIR_FORWARD;

                s->mv_type = MV_TYPE_16X16;

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

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

                s->mb_skipped = 1;

                *mb_type_ptr = MB_TYPE_SKIP | MB_TYPE_L0 | MB_TYPE_16x16;

                return 0;

            }

        }

        if(s->msmpeg4_version==2)

            code = get_vlc2(&s->gb, v2_mb_type_vlc.table, V2_MB_TYPE_VLC_BITS, 1);

        else

            code = get_vlc2(&s->gb, ff_h263_inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2);

        if(code<0 || code>7){

            av_log(s->avctx, AV_LOG_ERROR, "cbpc %d invalid at %d %d\n", code, s->mb_x, s->mb_y);

            return -1;

        }

        s->mb_intra = code >>2;

        cbp = code & 0x3;

    } else {

        s->mb_intra = 1;

        if(s->msmpeg4_version==2)

            cbp= get_vlc2(&s->gb, v2_intra_cbpc_vlc.table, V2_INTRA_CBPC_VLC_BITS, 1);

        else

            cbp= get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 1);

        if(cbp<0 || cbp>3){

            av_log(s->avctx, AV_LOG_ERROR, "cbpc %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y);

            return -1;

        }

    }

    if (!s->mb_intra) {

        int mx, my, cbpy;

        cbpy= get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1);

        if(cbpy<0){

            av_log(s->avctx, AV_LOG_ERROR, "cbpy %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y);

            return -1;

        }

        cbp|= cbpy<<2;

        if(s->msmpeg4_version==1 || (cbp&3) != 3) cbp^= 0x3C;

        ff_h263_pred_motion(s, 0, 0, &mx, &my);

        mx= msmpeg4v2_decode_motion(s, mx, 1);

        my= msmpeg4v2_decode_motion(s, my, 1);

        s->mv_dir = MV_DIR_FORWARD;

        s->mv_type = MV_TYPE_16X16;

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

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

        *mb_type_ptr = MB_TYPE_L0 | MB_TYPE_16x16;

    } else {

        if(s->msmpeg4_version==2){

            s->ac_pred = get_bits1(&s->gb);

            cbp|= get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors

        } else{

            s->ac_pred = 0;

            cbp|= get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors

            if(s->pict_type==AV_PICTURE_TYPE_P) cbp^=0x3C;

        }

        *mb_type_ptr = MB_TYPE_INTRA;

    }

    s->bdsp.clear_blocks(s->block[0]);

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

        if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0)

        {

             av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);

             return -1;

        }

    }

    return 0;

}


static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height)

{

    const uint8_t *frame_start = frame;

    const uint8_t *frame_end   = frame + width * height;

    int mask = 0x10000, bitbuf = 0;

    int v, count, segments;

    unsigned offset;

    segments = bytestream2_get_le32(gb);

    offset   = bytestream2_get_le32(gb);

    if (segments == 0 && offset == frame_end - frame)

        return 0; // skip frame

    if (frame_end - frame <= offset)

        return AVERROR_INVALIDDATA;

    frame += offset;

    while (segments--) {

        if (bytestream2_get_bytes_left(gb) < 2)

            return AVERROR_INVALIDDATA;

        if (mask == 0x10000) {

            bitbuf = bytestream2_get_le16u(gb);

            mask = 1;

        }

        if (frame_end - frame < 2)

            return AVERROR_INVALIDDATA;

        if (bitbuf & mask) {

            v = bytestream2_get_le16(gb);

            offset = (v & 0x1FFF) << 1;

            count = ((v >> 13) + 2) << 1;

            if (frame - frame_start < offset || frame_end - frame < count)

                return AVERROR_INVALIDDATA;

            av_memcpy_backptr(frame, offset, count);

            frame += count;

        } else {

            *frame++ = bytestream2_get_byte(gb);

            *frame++ = bytestream2_get_byte(gb);

        }

        mask <<= 1;

    }

    return 0;

}


static int qpel_motion_search(MpegEncContext * s,

				  int *mx_ptr, int *my_ptr, int dmin,

                                  int src_index, int ref_index,

                                  int size, int h)

{

    MotionEstContext * const c= &s->me;

    const int mx = *mx_ptr;

    const int my = *my_ptr;

    const int penalty_factor= c->sub_penalty_factor;

    const int map_generation= c->map_generation;

    const int subpel_quality= c->avctx->me_subpel_quality;

    uint32_t *map= c->map;

    me_cmp_func cmpf, chroma_cmpf;

    me_cmp_func cmp_sub, chroma_cmp_sub;

    LOAD_COMMON

    int flags= c->sub_flags;

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

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

 //FIXME factorize

    cmp_sub= s->dsp.me_sub_cmp[size];

    chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];

    if(c->skip){ //FIXME somehow move up (benchmark)

        *mx_ptr = 0;

        *my_ptr = 0;

        return dmin;

    }

    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){

        dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);

        if(mx || my || size>0)

            dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;

    }

    if (mx > xmin && mx < xmax &&

        my > ymin && my < ymax) {

        int bx=4*mx, by=4*my;

        int d= dmin;

        int i, nx, ny;

        const int index= (my<<ME_MAP_SHIFT) + mx;

        const int t= score_map[(index-(1<<ME_MAP_SHIFT)  )&(ME_MAP_SIZE-1)];

        const int l= score_map[(index- 1                 )&(ME_MAP_SIZE-1)];

        const int r= score_map[(index+ 1                 )&(ME_MAP_SIZE-1)];

        const int b= score_map[(index+(1<<ME_MAP_SHIFT)  )&(ME_MAP_SIZE-1)];

        const int c= score_map[(index                    )&(ME_MAP_SIZE-1)];

        int best[8];

        int best_pos[8][2];

        memset(best, 64, sizeof(int)*8);

#if 1

        if(s->me.dia_size>=2){

            const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];

            const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];

            const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];

            const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];

            for(ny= -3; ny <= 3; ny++){

                for(nx= -3; nx <= 3; nx++){

                    const int t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;

                    const int c2= nx*nx*( r +  l - 2*c) + 4*nx*( r- l) + 32*c;

                    const int b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;

                    int score= ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2;

                    int i;

                    if((nx&3)==0 && (ny&3)==0) continue;

                    score += 1024*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;

//                    if(nx&1) score-=1024*c->penalty_factor;

//                    if(ny&1) score-=1024*c->penalty_factor;

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

                        if(score < best[i]){

                            memmove(&best[i+1], &best[i], sizeof(int)*(7-i));

                            memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));

                            best[i]= score;

                            best_pos[i][0]= nx + 4*mx;

                            best_pos[i][1]= ny + 4*my;

                            break;

                        }

                    }

                }

            }

        }else{

            int tl;

            const int cx = 4*(r - l);

            const int cx2= r + l - 2*c;

            const int cy = 4*(b - t);

            const int cy2= b + t - 2*c;

            int cxy;

            if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME

                tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];

            }else{

                tl= cmp(s, mx-1, my-1, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);//FIXME wrong if chroma me is different

            }

            cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;

            assert(16*cx2 + 4*cx + 32*c == 32*r);

            assert(16*cx2 - 4*cx + 32*c == 32*l);

            assert(16*cy2 + 4*cy + 32*c == 32*b);

            assert(16*cy2 - 4*cy + 32*c == 32*t);

            assert(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);

            for(ny= -3; ny <= 3; ny++){

                for(nx= -3; nx <= 3; nx++){

                    int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor

                    int i;

                    if((nx&3)==0 && (ny&3)==0) continue;

                    score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;

//                    if(nx&1) score-=32*c->penalty_factor;

  //                  if(ny&1) score-=32*c->penalty_factor;

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

                        if(score < best[i]){

                            memmove(&best[i+1], &best[i], sizeof(int)*(7-i));

                            memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));

                            best[i]= score;

                            best_pos[i][0]= nx + 4*mx;

                            best_pos[i][1]= ny + 4*my;

                            break;

                        }

                    }

                }

            }

        }

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

            nx= best_pos[i][0];

            ny= best_pos[i][1];

            CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)

        }

#if 0

            const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];

            const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];

            const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];

            const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];

//            if(l < r && l < t && l < b && l < tl && l < bl && l < tr && l < br && bl < tl){

            if(tl<br){

//            nx= FFMAX(4*mx - bx, bx - 4*mx);

//            ny= FFMAX(4*my - by, by - 4*my);

            static int stats[7][7], count;

            count++;

            stats[4*mx - bx + 3][4*my - by + 3]++;

            if(256*256*256*64 % count ==0){

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

                    if((i%7)==0) printf("\n");

                    printf("%6d ", stats[0][i]);

                }

                printf("\n");

            }

            }

#endif

#else

        CHECK_QUARTER_MV(2, 2, mx-1, my-1)

        CHECK_QUARTER_MV(0, 2, mx  , my-1)

        CHECK_QUARTER_MV(2, 2, mx  , my-1)

        CHECK_QUARTER_MV(2, 0, mx  , my  )

        CHECK_QUARTER_MV(2, 2, mx  , my  )

        CHECK_QUARTER_MV(0, 2, mx  , my  )

        CHECK_QUARTER_MV(2, 2, mx-1, my  )

        CHECK_QUARTER_MV(2, 0, mx-1, my  )

        nx= bx;

        ny= by;

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

            int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1};

            int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1};

            CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2)

        }

#endif

#if 0

        //outer ring

        CHECK_QUARTER_MV(1, 3, mx-1, my-1)

        CHECK_QUARTER_MV(1, 2, mx-1, my-1)

        CHECK_QUARTER_MV(1, 1, mx-1, my-1)

        CHECK_QUARTER_MV(2, 1, mx-1, my-1)

        CHECK_QUARTER_MV(3, 1, mx-1, my-1)

        CHECK_QUARTER_MV(0, 1, mx  , my-1)

        CHECK_QUARTER_MV(1, 1, mx  , my-1)

        CHECK_QUARTER_MV(2, 1, mx  , my-1)

        CHECK_QUARTER_MV(3, 1, mx  , my-1)

        CHECK_QUARTER_MV(3, 2, mx  , my-1)

        CHECK_QUARTER_MV(3, 3, mx  , my-1)

        CHECK_QUARTER_MV(3, 0, mx  , my  )

        CHECK_QUARTER_MV(3, 1, mx  , my  )

        CHECK_QUARTER_MV(3, 2, mx  , my  )

        CHECK_QUARTER_MV(3, 3, mx  , my  )

        CHECK_QUARTER_MV(2, 3, mx  , my  )

        CHECK_QUARTER_MV(1, 3, mx  , my  )

        CHECK_QUARTER_MV(0, 3, mx  , my  )

        CHECK_QUARTER_MV(3, 3, mx-1, my  )

        CHECK_QUARTER_MV(2, 3, mx-1, my  )

        CHECK_QUARTER_MV(1, 3, mx-1, my  )

        CHECK_QUARTER_MV(1, 2, mx-1, my  )

        CHECK_QUARTER_MV(1, 1, mx-1, my  )

        CHECK_QUARTER_MV(1, 0, mx-1, my  )

#endif

        assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);

        *mx_ptr = bx;

        *my_ptr = by;

    }else{

        *mx_ptr =4*mx;

        *my_ptr =4*my;

    }

    return dmin;

}


void migrate_fd_error(MigrationState *s)

{

    trace_migrate_fd_error();

    assert(s->to_dst_file == NULL);

    migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,

                      MIGRATION_STATUS_FAILED);

    notifier_list_notify(&migration_state_notifiers, s);

}


static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint8_t addr, int size)

{

    uint32_t reg = (addr - TxStatus0) / 4;

    uint32_t offset = addr & 0x3;

    uint32_t ret = 0;

    if (addr & (size - 1)) {

        DPRINTF("not implemented read for TxStatus addr=0x%x size=0x%x\n", addr,

                size);

        return ret;

    }

    switch (size) {

    case 1: /* fall through */

    case 2: /* fall through */

    case 4:

        ret = (s->TxStatus[reg] >> offset * 8) & ((1 << (size * 8)) - 1);

        DPRINTF("TxStatus[%d] read addr=0x%x size=0x%x val=0x%08x\n", reg, addr,

                size, ret);

        break;

    default:

        DPRINTF("unsupported size 0x%x of TxStatus reading\n", size);

        break;

    }

    return ret;

}


static int decode_gop_header(IVI45DecContext *ctx, AVCodecContext *avctx)

{

    int             result, i, p, tile_size, pic_size_indx, mb_size, blk_size, is_scalable;

    int             quant_mat, blk_size_changed = 0;

    IVIBandDesc     *band, *band1, *band2;

    IVIPicConfig    pic_conf;

    ctx->gop_flags = get_bits(&ctx->gb, 8);

    ctx->gop_hdr_size = (ctx->gop_flags & 1) ? get_bits(&ctx->gb, 16) : 0;

    if (ctx->gop_flags & IVI5_IS_PROTECTED)

        ctx->lock_word = get_bits_long(&ctx->gb, 32);

    tile_size = (ctx->gop_flags & 0x40) ? 64 << get_bits(&ctx->gb, 2) : 0;

    if (tile_size > 256) {

        av_log(avctx, AV_LOG_ERROR, "Invalid tile size: %d\n", tile_size);

        return AVERROR_INVALIDDATA;

    }

    /* decode number of wavelet bands */

    /* num_levels * 3 + 1 */

    pic_conf.luma_bands   = get_bits(&ctx->gb, 2) * 3 + 1;

    pic_conf.chroma_bands = get_bits1(&ctx->gb)   * 3 + 1;

    is_scalable = pic_conf.luma_bands != 1 || pic_conf.chroma_bands != 1;

    if (is_scalable && (pic_conf.luma_bands != 4 || pic_conf.chroma_bands != 1)) {

        av_log(avctx, AV_LOG_ERROR, "Scalability: unsupported subdivision! Luma bands: %d, chroma bands: %d\n",

               pic_conf.luma_bands, pic_conf.chroma_bands);

        return AVERROR_INVALIDDATA;

    }

    pic_size_indx = get_bits(&ctx->gb, 4);

    if (pic_size_indx == IVI5_PIC_SIZE_ESC) {

        pic_conf.pic_height = get_bits(&ctx->gb, 13);

        pic_conf.pic_width  = get_bits(&ctx->gb, 13);

    } else {

        pic_conf.pic_height = ivi5_common_pic_sizes[pic_size_indx * 2 + 1] << 2;

        pic_conf.pic_width  = ivi5_common_pic_sizes[pic_size_indx * 2    ] << 2;

    }

    if (ctx->gop_flags & 2) {

        avpriv_report_missing_feature(avctx, "YV12 picture format");

        return AVERROR_PATCHWELCOME;

    }

    pic_conf.chroma_height = (pic_conf.pic_height + 3) >> 2;

    pic_conf.chroma_width  = (pic_conf.pic_width  + 3) >> 2;

    if (!tile_size) {

        pic_conf.tile_height = pic_conf.pic_height;

        pic_conf.tile_width  = pic_conf.pic_width;

    } else {

        pic_conf.tile_height = pic_conf.tile_width = tile_size;

    }

    /* check if picture layout was changed and reallocate buffers */

    if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf) || ctx->gop_invalid) {

        result = ff_ivi_init_planes(ctx->planes, &pic_conf, 0);

        if (result < 0) {

            av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n");

            return result;

        }

        ctx->pic_conf = pic_conf;

        ctx->is_scalable = is_scalable;

        blk_size_changed = 1; /* force reallocation of the internal structures */

    }

    for (p = 0; p <= 1; p++) {

        for (i = 0; i < (!p ? pic_conf.luma_bands : pic_conf.chroma_bands); i++) {

            band = &ctx->planes[p].bands[i];

            band->is_halfpel = get_bits1(&ctx->gb);

            mb_size  = get_bits1(&ctx->gb);

            blk_size = 8 >> get_bits1(&ctx->gb);

            mb_size  = blk_size << !mb_size;

            if (p==0 && blk_size==4) {

                av_log(avctx, AV_LOG_ERROR, "4x4 luma blocks are unsupported!\n");

                return AVERROR_PATCHWELCOME;

            }

            blk_size_changed = mb_size != band->mb_size || blk_size != band->blk_size;

            if (blk_size_changed) {

                band->mb_size  = mb_size;

                band->blk_size = blk_size;

            }

            if (get_bits1(&ctx->gb)) {

                avpriv_report_missing_feature(avctx, "Extended transform info");

                return AVERROR_PATCHWELCOME;

            }

            /* select transform function and scan pattern according to plane and band number */

            switch ((p << 2) + i) {

            case 0:

                band->inv_transform  = ff_ivi_inverse_slant_8x8;

                band->dc_transform   = ff_ivi_dc_slant_2d;

                band->scan           = ff_zigzag_direct;

                band->transform_size = 8;

                break;

            case 1:

                band->inv_transform  = ff_ivi_row_slant8;

                band->dc_transform   = ff_ivi_dc_row_slant;

                band->scan           = ff_ivi_vertical_scan_8x8;

                band->transform_size = 8;

                break;

            case 2:

                band->inv_transform  = ff_ivi_col_slant8;

                band->dc_transform   = ff_ivi_dc_col_slant;

                band->scan           = ff_ivi_horizontal_scan_8x8;

                band->transform_size = 8;

                break;

            case 3:

                band->inv_transform  = ff_ivi_put_pixels_8x8;

                band->dc_transform   = ff_ivi_put_dc_pixel_8x8;

                band->scan           = ff_ivi_horizontal_scan_8x8;

                band->transform_size = 8;

                break;

            case 4:

                band->inv_transform  = ff_ivi_inverse_slant_4x4;

                band->dc_transform   = ff_ivi_dc_slant_2d;

                band->scan           = ff_ivi_direct_scan_4x4;

                band->transform_size = 4;

                break;

            }

            band->is_2d_trans = band->inv_transform == ff_ivi_inverse_slant_8x8 ||

                                band->inv_transform == ff_ivi_inverse_slant_4x4;

            if (band->transform_size != band->blk_size) {

                av_log(avctx, AV_LOG_ERROR, "transform and block size mismatch (%d != %d)\n", band->transform_size, band->blk_size);

                return AVERROR_INVALIDDATA;

            }

            /* select dequant matrix according to plane and band number */

            if (!p) {

                quant_mat = (pic_conf.luma_bands > 1) ? i+1 : 0;

            } else {

                quant_mat = 5;

            }

            if (band->blk_size == 8) {

                if(quant_mat >= 5){

                    av_log(avctx, AV_LOG_ERROR, "quant_mat %d too large!\n", quant_mat);

                    return -1;

                }

                band->intra_base  = &ivi5_base_quant_8x8_intra[quant_mat][0];

                band->inter_base  = &ivi5_base_quant_8x8_inter[quant_mat][0];

                band->intra_scale = &ivi5_scale_quant_8x8_intra[quant_mat][0];

                band->inter_scale = &ivi5_scale_quant_8x8_inter[quant_mat][0];

            } else {

                band->intra_base  = ivi5_base_quant_4x4_intra;

                band->inter_base  = ivi5_base_quant_4x4_inter;

                band->intra_scale = ivi5_scale_quant_4x4_intra;

                band->inter_scale = ivi5_scale_quant_4x4_inter;

            }

            if (get_bits(&ctx->gb, 2)) {

                av_log(avctx, AV_LOG_ERROR, "End marker missing!\n");

                return AVERROR_INVALIDDATA;

            }

        }

    }

    /* copy chroma parameters into the 2nd chroma plane */

    for (i = 0; i < pic_conf.chroma_bands; i++) {

        band1 = &ctx->planes[1].bands[i];

        band2 = &ctx->planes[2].bands[i];

        band2->width         = band1->width;

        band2->height        = band1->height;

        band2->mb_size       = band1->mb_size;

        band2->blk_size      = band1->blk_size;

        band2->is_halfpel    = band1->is_halfpel;

        band2->intra_base    = band1->intra_base;

        band2->inter_base    = band1->inter_base;

        band2->intra_scale   = band1->intra_scale;

        band2->inter_scale   = band1->inter_scale;

        band2->scan          = band1->scan;

        band2->inv_transform = band1->inv_transform;

        band2->dc_transform  = band1->dc_transform;

        band2->is_2d_trans   = band1->is_2d_trans;

        band2->transform_size= band1->transform_size;

    }

    /* reallocate internal structures if needed */

    if (blk_size_changed) {

        result = ff_ivi_init_tiles(ctx->planes, pic_conf.tile_width,

                                   pic_conf.tile_height);

        if (result < 0) {

            av_log(avctx, AV_LOG_ERROR,

                   "Couldn't reallocate internal structures!\n");

            return result;

        }

    }

    if (ctx->gop_flags & 8) {

        if (get_bits(&ctx->gb, 3)) {

            av_log(avctx, AV_LOG_ERROR, "Alignment bits are not zero!\n");

            return AVERROR_INVALIDDATA;

        }

        if (get_bits1(&ctx->gb))

            skip_bits_long(&ctx->gb, 24); /* skip transparency fill color */

    }

    align_get_bits(&ctx->gb);

    skip_bits(&ctx->gb, 23); /* FIXME: unknown meaning */

    /* skip GOP extension if any */

    if (get_bits1(&ctx->gb)) {

        do {

            i = get_bits(&ctx->gb, 16);

        } while (i & 0x8000);

    }

    align_get_bits(&ctx->gb);

    return 0;

}


static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res)

{

    virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt);

    g_free(res->iov);

    res->iov = NULL;

    res->iov_cnt = 0;

}


static int get_packet(URLContext *s, int for_header)

{

    RTMPContext *rt = s->priv_data;

    int ret;

    uint8_t *p;

    const uint8_t *next;

    uint32_t data_size;

    uint32_t ts, cts, pts=0;

    if (rt->state == STATE_STOPPED)

        return AVERROR_EOF;

    for (;;) {

        RTMPPacket rpkt = { 0 };

        if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,

                                       rt->chunk_size, rt->prev_pkt[0])) <= 0) {

            if (ret == 0) {

                return AVERROR(EAGAIN);

            } else {

                return AVERROR(EIO);

            }

        }

        rt->bytes_read += ret;

        if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {

            av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");

            gen_bytes_read(s, rt, rpkt.timestamp + 1);

            rt->last_bytes_read = rt->bytes_read;

        }

        ret = rtmp_parse_result(s, rt, &rpkt);

        if (ret < 0) {//serious error in current packet

            ff_rtmp_packet_destroy(&rpkt);

            return -1;

        }

        if (rt->state == STATE_STOPPED) {

            ff_rtmp_packet_destroy(&rpkt);

            return AVERROR_EOF;

        }

        if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {

            ff_rtmp_packet_destroy(&rpkt);

            return 0;

        }

        if (!rpkt.data_size || !rt->is_input) {

            ff_rtmp_packet_destroy(&rpkt);

            continue;

        }

        if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||

           (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {

            ts = rpkt.timestamp;

            // generate packet header and put data into buffer for FLV demuxer

            rt->flv_off  = 0;

            rt->flv_size = rpkt.data_size + 15;

            rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);

            bytestream_put_byte(&p, rpkt.type);

            bytestream_put_be24(&p, rpkt.data_size);

            bytestream_put_be24(&p, ts);

            bytestream_put_byte(&p, ts >> 24);

            bytestream_put_be24(&p, 0);

            bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);

            bytestream_put_be32(&p, 0);

            ff_rtmp_packet_destroy(&rpkt);

            return 0;

        } else if (rpkt.type == RTMP_PT_METADATA) {

            // we got raw FLV data, make it available for FLV demuxer

            rt->flv_off  = 0;

            rt->flv_size = rpkt.data_size;

            rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);

            /* rewrite timestamps */

            next = rpkt.data;

            ts = rpkt.timestamp;

            while (next - rpkt.data < rpkt.data_size - 11) {

                next++;

                data_size = bytestream_get_be24(&next);

                p=next;

                cts = bytestream_get_be24(&next);

                cts |= bytestream_get_byte(&next) << 24;

                if (pts==0)

                    pts=cts;

                ts += cts - pts;

                pts = cts;

                bytestream_put_be24(&p, ts);

                bytestream_put_byte(&p, ts >> 24);

                next += data_size + 3 + 4;

            }

            memcpy(rt->flv_data, rpkt.data, rpkt.data_size);

            ff_rtmp_packet_destroy(&rpkt);

            return 0;

        }

        ff_rtmp_packet_destroy(&rpkt);

    }

    return 0;

}