void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,

                                int log2_trafo_size, enum ScanType scan_idx,

                                int c_idx)

{

#define GET_COORD(offset, n)                                    \

    do {                                                        \

        x_c = (x_cg << 2) + scan_x_off[n];                      \

        y_c = (y_cg << 2) + scan_y_off[n];                      \

    } while (0)

    HEVCLocalContext *lc = s->HEVClc;

    int transform_skip_flag = 0;

    int last_significant_coeff_x, last_significant_coeff_y;

    int last_scan_pos;

    int n_end;

    int num_coeff = 0;

    int greater1_ctx = 1;

    int num_last_subset;

    int x_cg_last_sig, y_cg_last_sig;

    const uint8_t *scan_x_cg, *scan_y_cg, *scan_x_off, *scan_y_off;

    ptrdiff_t stride = s->frame->linesize[c_idx];

    int hshift = s->sps->hshift[c_idx];

    int vshift = s->sps->vshift[c_idx];

    uint8_t *dst = &s->frame->data[c_idx][(y0 >> vshift) * stride +

                                          ((x0 >> hshift) << s->sps->pixel_shift)];

    int16_t *coeffs = lc->tu.coeffs[c_idx > 0];

    uint8_t significant_coeff_group_flag[8][8] = {{0}};

    int explicit_rdpcm_flag = 0;

    int explicit_rdpcm_dir_flag;

    int trafo_size = 1 << log2_trafo_size;

    int i;

    int qp,shift,add,scale,scale_m;

    const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 };

    const uint8_t *scale_matrix = NULL;

    uint8_t dc_scale;

    int pred_mode_intra = (c_idx == 0) ? lc->tu.intra_pred_mode :

                                         lc->tu.intra_pred_mode_c;

    memset(coeffs, 0, trafo_size * trafo_size * sizeof(int16_t));

    // Derive QP for dequant

    if (!lc->cu.cu_transquant_bypass_flag) {

        static const int qp_c[] = { 29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37 };

        static const uint8_t rem6[51 + 4 * 6 + 1] = {

            0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2,

            3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,

            0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3,

            4, 5, 0, 1, 2, 3, 4, 5, 0, 1

        };

        static const uint8_t div6[51 + 4 * 6 + 1] = {

            0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3,  3,  3,

            3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,  6,  6,

            7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10,

            10, 10, 11, 11, 11, 11, 11, 11, 12, 12

        };

        int qp_y = lc->qp_y;

        if (s->pps->transform_skip_enabled_flag &&

            log2_trafo_size <= s->pps->log2_max_transform_skip_block_size) {

            transform_skip_flag = ff_hevc_transform_skip_flag_decode(s, c_idx);

        }

        if (c_idx == 0) {

            qp = qp_y + s->sps->qp_bd_offset;

        } else {

            int qp_i, offset;

            if (c_idx == 1)

                offset = s->pps->cb_qp_offset + s->sh.slice_cb_qp_offset +

                         lc->tu.cu_qp_offset_cb;

            else

                offset = s->pps->cr_qp_offset + s->sh.slice_cr_qp_offset +

                         lc->tu.cu_qp_offset_cr;

            qp_i = av_clip(qp_y + offset, - s->sps->qp_bd_offset, 57);

            if (s->sps->chroma_format_idc == 1) {

                if (qp_i < 30)

                    qp = qp_i;

                else if (qp_i > 43)

                    qp = qp_i - 6;

                else

                    qp = qp_c[qp_i - 30];

            } else {

                if (qp_i > 51)

                    qp = 51;

                else

                    qp = qp_i;

            }

            qp += s->sps->qp_bd_offset;

        }

        shift    = s->sps->bit_depth + log2_trafo_size - 5;

        add      = 1 << (shift-1);

        scale    = level_scale[rem6[qp]] << (div6[qp]);

        scale_m  = 16; // default when no custom scaling lists.

        dc_scale = 16;

        if (s->sps->scaling_list_enable_flag && !(transform_skip_flag && log2_trafo_size > 2)) {

            const ScalingList *sl = s->pps->scaling_list_data_present_flag ?

            &s->pps->scaling_list : &s->sps->scaling_list;

            int matrix_id = lc->cu.pred_mode != MODE_INTRA;

            matrix_id = 3 * matrix_id + c_idx;

            scale_matrix = sl->sl[log2_trafo_size - 2][matrix_id];

            if (log2_trafo_size >= 4)

                dc_scale = sl->sl_dc[log2_trafo_size - 4][matrix_id];

        }

    } else {

        shift        = 0;

        add          = 0;

        scale        = 0;

        dc_scale     = 0;

    }

    if (lc->cu.pred_mode == MODE_INTER && s->sps->explicit_rdpcm_enabled_flag &&

        (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) {

        explicit_rdpcm_flag = explicit_rdpcm_flag_decode(s, c_idx);

        if (explicit_rdpcm_flag) {

            explicit_rdpcm_dir_flag = explicit_rdpcm_dir_flag_decode(s, c_idx);

        }

    }

    last_significant_coeff_xy_prefix_decode(s, c_idx, log2_trafo_size,

                                           &last_significant_coeff_x, &last_significant_coeff_y);

    if (last_significant_coeff_x > 3) {

        int suffix = last_significant_coeff_suffix_decode(s, last_significant_coeff_x);

        last_significant_coeff_x = (1 << ((last_significant_coeff_x >> 1) - 1)) *

        (2 + (last_significant_coeff_x & 1)) +

        suffix;

    }

    if (last_significant_coeff_y > 3) {

        int suffix = last_significant_coeff_suffix_decode(s, last_significant_coeff_y);

        last_significant_coeff_y = (1 << ((last_significant_coeff_y >> 1) - 1)) *

        (2 + (last_significant_coeff_y & 1)) +

        suffix;

    }

    if (scan_idx == SCAN_VERT)

        FFSWAP(int, last_significant_coeff_x, last_significant_coeff_y);

    x_cg_last_sig = last_significant_coeff_x >> 2;

    y_cg_last_sig = last_significant_coeff_y >> 2;

    switch (scan_idx) {

    case SCAN_DIAG: {

        int last_x_c = last_significant_coeff_x & 3;

        int last_y_c = last_significant_coeff_y & 3;

        scan_x_off = ff_hevc_diag_scan4x4_x;

        scan_y_off = ff_hevc_diag_scan4x4_y;

        num_coeff = diag_scan4x4_inv[last_y_c][last_x_c];

        if (trafo_size == 4) {

            scan_x_cg = scan_1x1;

            scan_y_cg = scan_1x1;

        } else if (trafo_size == 8) {

            num_coeff += diag_scan2x2_inv[y_cg_last_sig][x_cg_last_sig] << 4;

            scan_x_cg = diag_scan2x2_x;

            scan_y_cg = diag_scan2x2_y;

        } else if (trafo_size == 16) {

            num_coeff += diag_scan4x4_inv[y_cg_last_sig][x_cg_last_sig] << 4;

            scan_x_cg = ff_hevc_diag_scan4x4_x;

            scan_y_cg = ff_hevc_diag_scan4x4_y;

        } else { // trafo_size == 32

            num_coeff += diag_scan8x8_inv[y_cg_last_sig][x_cg_last_sig] << 4;

            scan_x_cg = ff_hevc_diag_scan8x8_x;

            scan_y_cg = ff_hevc_diag_scan8x8_y;

        }

        break;

    }

    case SCAN_HORIZ:

        scan_x_cg = horiz_scan2x2_x;

        scan_y_cg = horiz_scan2x2_y;

        scan_x_off = horiz_scan4x4_x;

        scan_y_off = horiz_scan4x4_y;

        num_coeff = horiz_scan8x8_inv[last_significant_coeff_y][last_significant_coeff_x];

        break;

    default: //SCAN_VERT

        scan_x_cg = horiz_scan2x2_y;

        scan_y_cg = horiz_scan2x2_x;

        scan_x_off = horiz_scan4x4_y;

        scan_y_off = horiz_scan4x4_x;

        num_coeff = horiz_scan8x8_inv[last_significant_coeff_x][last_significant_coeff_y];

        break;

    }

    num_coeff++;

    num_last_subset = (num_coeff - 1) >> 4;

    for (i = num_last_subset; i >= 0; i--) {

        int n, m;

        int x_cg, y_cg, x_c, y_c, pos;

        int implicit_non_zero_coeff = 0;

        int64_t trans_coeff_level;

        int prev_sig = 0;

        int offset = i << 4;

        int rice_init = 0;

        uint8_t significant_coeff_flag_idx[16];

        uint8_t nb_significant_coeff_flag = 0;

        x_cg = scan_x_cg[i];

        y_cg = scan_y_cg[i];

        if ((i < num_last_subset) && (i > 0)) {

            int ctx_cg = 0;

            if (x_cg < (1 << (log2_trafo_size - 2)) - 1)

                ctx_cg += significant_coeff_group_flag[x_cg + 1][y_cg];

            if (y_cg < (1 << (log2_trafo_size - 2)) - 1)

                ctx_cg += significant_coeff_group_flag[x_cg][y_cg + 1];

            significant_coeff_group_flag[x_cg][y_cg] =

                significant_coeff_group_flag_decode(s, c_idx, ctx_cg);

            implicit_non_zero_coeff = 1;

        } else {

            significant_coeff_group_flag[x_cg][y_cg] =

            ((x_cg == x_cg_last_sig && y_cg == y_cg_last_sig) ||

             (x_cg == 0 && y_cg == 0));

        }

        last_scan_pos = num_coeff - offset - 1;

        if (i == num_last_subset) {

            n_end = last_scan_pos - 1;

            significant_coeff_flag_idx[0] = last_scan_pos;

            nb_significant_coeff_flag = 1;

        } else {

            n_end = 15;

        }

        if (x_cg < ((1 << log2_trafo_size) - 1) >> 2)

            prev_sig = !!significant_coeff_group_flag[x_cg + 1][y_cg];

        if (y_cg < ((1 << log2_trafo_size) - 1) >> 2)

            prev_sig += (!!significant_coeff_group_flag[x_cg][y_cg + 1] << 1);

        if (significant_coeff_group_flag[x_cg][y_cg] && n_end >= 0) {

            static const uint8_t ctx_idx_map[] = {

                0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8, // log2_trafo_size == 2

                1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // prev_sig == 0

                2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, // prev_sig == 1

                2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, // prev_sig == 2

                2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2  // default

            };

            const uint8_t *ctx_idx_map_p;

            int scf_offset = 0;

            if (s->sps->transform_skip_context_enabled_flag &&

                (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) {

                ctx_idx_map_p = (uint8_t*) &ctx_idx_map[4 * 16];

                if (c_idx == 0) {

                    scf_offset = 40;

                } else {

                    scf_offset = 14 + 27;

                }

            } else {

                if (c_idx != 0)

                    scf_offset = 27;

                if (log2_trafo_size == 2) {

                    ctx_idx_map_p = (uint8_t*) &ctx_idx_map[0];

                } else {

                    ctx_idx_map_p = (uint8_t*) &ctx_idx_map[(prev_sig + 1) << 4];

                    if (c_idx == 0) {

                        if ((x_cg > 0 || y_cg > 0))

                            scf_offset += 3;

                        if (log2_trafo_size == 3) {

                            scf_offset += (scan_idx == SCAN_DIAG) ? 9 : 15;

                        } else {

                            scf_offset += 21;

                        }

                    } else {

                        if (log2_trafo_size == 3)

                            scf_offset += 9;

                        else

                            scf_offset += 12;

                    }

                }

            }

            for (n = n_end; n > 0; n--) {

                x_c = scan_x_off[n];

                y_c = scan_y_off[n];

                if (significant_coeff_flag_decode(s, x_c, y_c, scf_offset, ctx_idx_map_p)) {

                    significant_coeff_flag_idx[nb_significant_coeff_flag] = n;

                    nb_significant_coeff_flag++;

                    implicit_non_zero_coeff = 0;

                }

            }

            if (implicit_non_zero_coeff == 0) {

                if (s->sps->transform_skip_context_enabled_flag &&

                    (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) {

                    if (c_idx == 0) {

                        scf_offset = 42;

                    } else {

                        scf_offset = 16 + 27;

                    }

                } else {

                    if (i == 0) {

                        if (c_idx == 0)

                            scf_offset = 0;

                        else

                            scf_offset = 27;

                    } else {

                        scf_offset = 2 + scf_offset;

                    }

                }

                if (significant_coeff_flag_decode_0(s, c_idx, scf_offset) == 1) {

                    significant_coeff_flag_idx[nb_significant_coeff_flag] = 0;

                    nb_significant_coeff_flag++;

                }

            } else {

                significant_coeff_flag_idx[nb_significant_coeff_flag] = 0;

                nb_significant_coeff_flag++;

            }

        }

        n_end = nb_significant_coeff_flag;

        if (n_end) {

            int first_nz_pos_in_cg;

            int last_nz_pos_in_cg;

            int c_rice_param = 0;

            int first_greater1_coeff_idx = -1;

            uint8_t coeff_abs_level_greater1_flag[8];

            uint16_t coeff_sign_flag;

            int sum_abs = 0;

            int sign_hidden;

            int sb_type;

            // initialize first elem of coeff_bas_level_greater1_flag

            int ctx_set = (i > 0 && c_idx == 0) ? 2 : 0;

            if (s->sps->persistent_rice_adaptation_enabled_flag) {

                if (!transform_skip_flag && !lc->cu.cu_transquant_bypass_flag)

                    sb_type = 2 * (c_idx == 0 ? 1 : 0);

                else

                    sb_type = 2 * (c_idx == 0 ? 1 : 0) + 1;

                c_rice_param = lc->stat_coeff[sb_type] / 4;

            }

            if (!(i == num_last_subset) && greater1_ctx == 0)

                ctx_set++;

            greater1_ctx = 1;

            last_nz_pos_in_cg = significant_coeff_flag_idx[0];

            for (m = 0; m < (n_end > 8 ? 8 : n_end); m++) {

                int inc = (ctx_set << 2) + greater1_ctx;

                coeff_abs_level_greater1_flag[m] =

                    coeff_abs_level_greater1_flag_decode(s, c_idx, inc);

                if (coeff_abs_level_greater1_flag[m]) {

                    greater1_ctx = 0;

                    if (first_greater1_coeff_idx == -1)

                        first_greater1_coeff_idx = m;

                } else if (greater1_ctx > 0 && greater1_ctx < 3) {

                    greater1_ctx++;

                }

            }

            first_nz_pos_in_cg = significant_coeff_flag_idx[n_end - 1];

            if (lc->cu.cu_transquant_bypass_flag ||

                (lc->cu.pred_mode ==  MODE_INTRA  &&

                 s->sps->implicit_rdpcm_enabled_flag  &&  transform_skip_flag  &&

                 (pred_mode_intra == 10 || pred_mode_intra  ==  26 )) ||

                 explicit_rdpcm_flag)

                sign_hidden = 0;

            else

                sign_hidden = (last_nz_pos_in_cg - first_nz_pos_in_cg >= 4);

            if (first_greater1_coeff_idx != -1) {

                coeff_abs_level_greater1_flag[first_greater1_coeff_idx] += coeff_abs_level_greater2_flag_decode(s, c_idx, ctx_set);

            }

            if (!s->pps->sign_data_hiding_flag || !sign_hidden ) {

                coeff_sign_flag = coeff_sign_flag_decode(s, nb_significant_coeff_flag) << (16 - nb_significant_coeff_flag);

            } else {

                coeff_sign_flag = coeff_sign_flag_decode(s, nb_significant_coeff_flag - 1) << (16 - (nb_significant_coeff_flag - 1));

            }

            for (m = 0; m < n_end; m++) {

                n = significant_coeff_flag_idx[m];

                GET_COORD(offset, n);

                if (m < 8) {

                    trans_coeff_level = 1 + coeff_abs_level_greater1_flag[m];

                    if (trans_coeff_level == ((m == first_greater1_coeff_idx) ? 3 : 2)) {

                        int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param);

                        trans_coeff_level += last_coeff_abs_level_remaining;

                        if (trans_coeff_level > (3 << c_rice_param))

                            c_rice_param = s->sps->persistent_rice_adaptation_enabled_flag ? c_rice_param + 1 : FFMIN(c_rice_param + 1, 4);

                        if (s->sps->persistent_rice_adaptation_enabled_flag && !rice_init) {

                            int c_rice_p_init = lc->stat_coeff[sb_type] / 4;

                            if (last_coeff_abs_level_remaining >= (3 << c_rice_p_init))

                                lc->stat_coeff[sb_type]++;

                            else if (2 * last_coeff_abs_level_remaining < (1 << c_rice_p_init))

                                if (lc->stat_coeff[sb_type] > 0)

                                    lc->stat_coeff[sb_type]--;

                            rice_init = 1;

                        }

                    }

                } else {

                    int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param);

                    trans_coeff_level = 1 + last_coeff_abs_level_remaining;

                    if (trans_coeff_level > (3 << c_rice_param))

                        c_rice_param = s->sps->persistent_rice_adaptation_enabled_flag ? c_rice_param + 1 : FFMIN(c_rice_param + 1, 4);

                    if (s->sps->persistent_rice_adaptation_enabled_flag && !rice_init) {

                        int c_rice_p_init = lc->stat_coeff[sb_type] / 4;

                        if (last_coeff_abs_level_remaining >= (3 << c_rice_p_init))

                            lc->stat_coeff[sb_type]++;

                        else if (2 * last_coeff_abs_level_remaining < (1 << c_rice_p_init))

                            if (lc->stat_coeff[sb_type] > 0)

                                lc->stat_coeff[sb_type]--;

                        rice_init = 1;

                    }

                }

                if (s->pps->sign_data_hiding_flag && sign_hidden) {

                    sum_abs += trans_coeff_level;

                    if (n == first_nz_pos_in_cg && (sum_abs&1))

                        trans_coeff_level = -trans_coeff_level;

                }

                if (coeff_sign_flag >> 15)

                    trans_coeff_level = -trans_coeff_level;

                coeff_sign_flag <<= 1;

                if(!lc->cu.cu_transquant_bypass_flag) {

                    if (s->sps->scaling_list_enable_flag && !(transform_skip_flag && log2_trafo_size > 2)) {

                        if(y_c || x_c || log2_trafo_size < 4) {

                            switch(log2_trafo_size) {

                                case 3: pos = (y_c << 3) + x_c; break;

                                case 4: pos = ((y_c >> 1) << 3) + (x_c >> 1); break;

                                case 5: pos = ((y_c >> 2) << 3) + (x_c >> 2); break;

                                default: pos = (y_c << 2) + x_c; break;

                            }

                            scale_m = scale_matrix[pos];

                        } else {

                            scale_m = dc_scale;

                        }

                    }

                    trans_coeff_level = (trans_coeff_level * (int64_t)scale * (int64_t)scale_m + add) >> shift;

                    if(trans_coeff_level < 0) {

                        if((~trans_coeff_level) & 0xFffffffffff8000)

                            trans_coeff_level = -32768;

                    } else {

                        if(trans_coeff_level & 0xffffffffffff8000)

                            trans_coeff_level = 32767;

                    }

                }

                coeffs[y_c * trafo_size + x_c] = trans_coeff_level;

            }

        }

    }

    if (lc->cu.cu_transquant_bypass_flag) {

        if (explicit_rdpcm_flag || (s->sps->implicit_rdpcm_enabled_flag &&

                                    (pred_mode_intra == 10 || pred_mode_intra == 26))) {

            int mode = s->sps->implicit_rdpcm_enabled_flag ? (pred_mode_intra == 26) : explicit_rdpcm_dir_flag;

            s->hevcdsp.transform_rdpcm(coeffs, log2_trafo_size, mode);

        }

    } else {

        if (transform_skip_flag) {

            int rot = s->sps->transform_skip_rotation_enabled_flag &&

                      log2_trafo_size == 2 &&

                      lc->cu.pred_mode == MODE_INTRA;

            if (rot) {

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

                    FFSWAP(int16_t, coeffs[i], coeffs[16 - i - 1]);

            }

            s->hevcdsp.transform_skip(coeffs, log2_trafo_size);

            if (explicit_rdpcm_flag || (s->sps->implicit_rdpcm_enabled_flag &&

                                        lc->cu.pred_mode == MODE_INTRA &&

                                        (pred_mode_intra == 10 || pred_mode_intra == 26))) {

                int mode = explicit_rdpcm_flag ? explicit_rdpcm_dir_flag : (pred_mode_intra == 26);

                s->hevcdsp.transform_rdpcm(coeffs, log2_trafo_size, mode);

            }

        } else if (lc->cu.pred_mode == MODE_INTRA && c_idx == 0 && log2_trafo_size == 2) {

            s->hevcdsp.idct_4x4_luma(coeffs);

        } else {

            int max_xy = FFMAX(last_significant_coeff_x, last_significant_coeff_y);

            if (max_xy == 0)

                s->hevcdsp.idct_dc[log2_trafo_size-2](coeffs);

            else {

                int col_limit = last_significant_coeff_x + last_significant_coeff_y + 4;

                if (max_xy < 4)

                    col_limit = FFMIN(4, col_limit);

                else if (max_xy < 8)

                    col_limit = FFMIN(8, col_limit);

                else if (max_xy < 12)

                    col_limit = FFMIN(24, col_limit);

                s->hevcdsp.idct[log2_trafo_size-2](coeffs, col_limit);

            }

        }

    }

    if (lc->tu.cross_pf) {

        int16_t *coeffs_y = lc->tu.coeffs[0];

        for (i = 0; i < (trafo_size * trafo_size); i++) {

            coeffs[i] = coeffs[i] + ((lc->tu.res_scale_val * coeffs_y[i]) >> 3);

        }

    }

    s->hevcdsp.transform_add[log2_trafo_size-2](dst, coeffs, stride);

}


static int mov_write_sidx_tag(AVIOContext *pb,

                              MOVTrack *track, int ref_size, int total_sidx_size)

{

    int64_t pos = avio_tell(pb), offset_pos, end_pos;

    int64_t presentation_time, duration, offset;

    int starts_with_SAP, i, entries;

    if (track->entry) {

        entries = 1;

        presentation_time = track->start_dts + track->frag_start +

                            track->cluster[0].cts;

        duration = track->end_pts -

                   (track->cluster[0].dts + track->cluster[0].cts);

        starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;

        // pts<0 should be cut away using edts

        if (presentation_time < 0) {

            duration += presentation_time;

            presentation_time = 0;

        }

    } else {

        entries = track->nb_frag_info;

        presentation_time = track->frag_info[0].time;

    }

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

    ffio_wfourcc(pb, "sidx");

    avio_w8(pb, 1); /* version */

    avio_wb24(pb, 0);

    avio_wb32(pb, track->track_id); /* reference_ID */

    avio_wb32(pb, track->timescale); /* timescale */

    avio_wb64(pb, presentation_time); /* earliest_presentation_time */

    offset_pos = avio_tell(pb);

    avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */

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

    avio_wb16(pb, entries); /* reference_count */

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

        if (!track->entry) {

            if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {

               av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");

            }

            duration = track->frag_info[i].duration;

            ref_size = track->frag_info[i].size;

            starts_with_SAP = 1;

        }

        avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */

        avio_wb32(pb, duration); /* subsegment_duration */

        avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */

    }

    end_pos = avio_tell(pb);

    offset = pos + total_sidx_size - end_pos;

    avio_seek(pb, offset_pos, SEEK_SET);

    avio_wb64(pb, offset);

    avio_seek(pb, end_pos, SEEK_SET);

    return update_size(pb, pos);

}


static uint64_t vfio_rtl8168_window_quirk_read(void *opaque,

                                               hwaddr addr, unsigned size)

{

    VFIOQuirk *quirk = opaque;

    VFIOPCIDevice *vdev = quirk->vdev;

    switch (addr) {

    case 4: /* address */

        if (quirk->data.flags) {

            trace_vfio_rtl8168_window_quirk_read_fake(

                    memory_region_name(&quirk->mem),

                    vdev->vbasedev.name);

            return quirk->data.address_match ^ 0x80000000U;

        }

        break;

    case 0: /* data */

        if (quirk->data.flags) {

            uint64_t val;

            trace_vfio_rtl8168_window_quirk_read_table(

                    memory_region_name(&quirk->mem),

                    vdev->vbasedev.name);

            if (!(vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) {

                return 0;

            }

            memory_region_dispatch_read(&vdev->pdev.msix_table_mmio,

                                        (hwaddr)(quirk->data.address_match

                                                 & 0xfff),

                                        &val,

                                        size,

                                        MEMTXATTRS_UNSPECIFIED);

            return val;

        }

    }

    trace_vfio_rtl8168_window_quirk_read_direct(memory_region_name(&quirk->mem),

                                                vdev->vbasedev.name);

    return vfio_region_read(&vdev->bars[quirk->data.bar].region,

                            addr + 0x70, size);

}


static int teletext_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *pkt)

{

    TeletextContext *ctx = avctx->priv_data;

    AVSubtitle      *sub = data;

    const uint8_t   *buf = pkt->data;

    int             left = pkt->size;

    uint8_t         pesheader[45] = {0x00, 0x00, 0x01, 0xbd, 0x00, 0x00, 0x85, 0x80, 0x24, 0x21, 0x00, 0x01, 0x00, 0x01};

    int             pesheader_size = sizeof(pesheader);

    const uint8_t   *pesheader_buf = pesheader;

    int             ret = 0;

    if (!ctx->vbi) {

        if (!(ctx->vbi = vbi_decoder_new()))

            return AVERROR(ENOMEM);

        if (!vbi_event_handler_add(ctx->vbi, VBI_EVENT_TTX_PAGE, handler, ctx)) {

            vbi_decoder_delete(ctx->vbi);

            ctx->vbi = NULL;

            return AVERROR(ENOMEM);

        }

    }

    if (!ctx->dx && (!(ctx->dx = vbi_dvb_pes_demux_new (/* callback */ NULL, NULL))))

        return AVERROR(ENOMEM);

    if (avctx->pkt_timebase.den && pkt->pts != AV_NOPTS_VALUE)

        ctx->pts = av_rescale_q(pkt->pts, avctx->pkt_timebase, AV_TIME_BASE_Q);

    if (left) {

        // We allow unreasonably big packets, even if the standard only allows a max size of 1472

        if ((pesheader_size + left) < 184 || (pesheader_size + left) > 65504 || (pesheader_size + left) % 184 != 0)

            return AVERROR_INVALIDDATA;

        memset(pesheader + 14, 0xff, pesheader_size - 14);

        AV_WB16(pesheader + 4, left + pesheader_size - 6);

        /* PTS is deliberately left as 0 in the PES header, otherwise libzvbi uses

         * it to detect dropped frames. Unforunatey the guessed packet PTS values

         * (see mpegts demuxer) are not accurate enough to pass that test. */

        vbi_dvb_demux_cor(ctx->dx, ctx->sliced, 64, NULL, &pesheader_buf, &pesheader_size);

        ctx->handler_ret = pkt->size;

        while (left > 0) {

            int64_t pts = 0;

            unsigned int lines = vbi_dvb_demux_cor(ctx->dx, ctx->sliced, 64, &pts, &buf, &left);

            av_dlog(avctx, "ctx=%p buf_size=%d left=%u lines=%u pts=%f pkt_pts=%f\n",

                    ctx, pkt->size, left, lines, (double)pts/90000.0, (double)pkt->pts/90000.0);

            if (lines > 0) {

#ifdef DEBUGx

                int i;

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

                    av_log(avctx, AV_LOG_DEBUG,

                           "lines=%d id=%x\n", i, ctx->sliced[i].id);

#endif

                vbi_decode(ctx->vbi, ctx->sliced, lines, (double)pts/90000.0);

                ctx->lines_processed += lines;

            }

        }

        ctx->pts = AV_NOPTS_VALUE;

        ret = ctx->handler_ret;

    }

    if (ret < 0)

        return ret;

    // is there a subtitle to pass?

    if (ctx->nb_pages) {

        int i;

        sub->format = ctx->format_id;

        sub->start_display_time = 0;

        sub->end_display_time = ctx->sub_duration;

        sub->num_rects = 0;

        sub->pts = ctx->pages->pts;

        if (ctx->pages->sub_rect->type != SUBTITLE_NONE) {

            sub->rects = av_malloc(sizeof(*sub->rects) * 1);

            if (sub->rects) {

                sub->num_rects = 1;

                sub->rects[0] = ctx->pages->sub_rect;

            } else {

                ret = AVERROR(ENOMEM);

            }

        } else {

            av_log(avctx, AV_LOG_DEBUG, "sending empty sub\n");

            sub->rects = NULL;

        }

        if (!sub->rects) // no rect was passed

            subtitle_rect_free(&ctx->pages->sub_rect);

        for (i = 0; i < ctx->nb_pages - 1; i++)

            ctx->pages[i] = ctx->pages[i + 1];

        ctx->nb_pages--;

        if (ret >= 0)

            *data_size = 1;

    } else

        *data_size = 0;

    return ret;

}


static int enable_write_target(BlockDriverState *bs, Error **errp)

{

    BDRVVVFATState *s = bs->opaque;

    BlockDriver *bdrv_qcow = NULL;

    BlockDriverState *backing;

    QemuOpts *opts = NULL;

    int ret;

    int size = sector2cluster(s, s->sector_count);

    QDict *options;

    s->used_clusters = calloc(size, 1);

    array_init(&(s->commits), sizeof(commit_t));

    s->qcow_filename = g_malloc(PATH_MAX);

    ret = get_tmp_filename(s->qcow_filename, PATH_MAX);

    if (ret < 0) {

        error_setg_errno(errp, -ret, "can't create temporary file");

        goto err;

    }

    bdrv_qcow = bdrv_find_format("qcow");

    if (!bdrv_qcow) {

        error_setg(errp, "Failed to locate qcow driver");

        ret = -ENOENT;

        goto err;

    }

    opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);

    qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512,

                        &error_abort);

    qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);

    ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);

    qemu_opts_del(opts);

    if (ret < 0) {

        goto err;

    }

    options = qdict_new();

    qdict_put(options, "write-target.driver", qstring_from_str("qcow"));

    s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,

                              &child_vvfat_qcow, false, errp);

    QDECREF(options);

    if (!s->qcow) {

        ret = -EINVAL;

        goto err;

    }

#ifndef _WIN32

    unlink(s->qcow_filename);

#endif

    backing = bdrv_new();

    bdrv_set_backing_hd(s->bs, backing);

    bdrv_unref(backing);

    s->bs->backing->bs->drv = &vvfat_write_target;

    s->bs->backing->bs->opaque = g_new(void *, 1);

    *(void**)s->bs->backing->bs->opaque = s;

    return 0;

err:

    g_free(s->qcow_filename);

    s->qcow_filename = NULL;

    return ret;

}


static int apng_read_header(AVFormatContext *s)

{

    APNGDemuxContext *ctx = s->priv_data;

    AVIOContext *pb = s->pb;

    uint32_t len, tag;

    AVStream *st;

    int acTL_found = 0;

    int64_t ret = AVERROR_INVALIDDATA;

    /* verify PNGSIG */

    if (avio_rb64(pb) != PNGSIG)

        return ret;

    /* parse IHDR (must be first chunk) */

    len = avio_rb32(pb);

    tag = avio_rl32(pb);

    if (len != 13 || tag != MKTAG('I', 'H', 'D', 'R'))

        return ret;

    st = avformat_new_stream(s, NULL);

    if (!st)

        return AVERROR(ENOMEM);

    /* set the timebase to something large enough (1/100,000 of second)

     * to hopefully cope with all sane frame durations */

    avpriv_set_pts_info(st, 64, 1, 100000);

    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;

    st->codecpar->codec_id   = AV_CODEC_ID_APNG;

    st->codecpar->width      = avio_rb32(pb);

    st->codecpar->height     = avio_rb32(pb);

    if ((ret = av_image_check_size(st->codecpar->width, st->codecpar->height, 0, s)) < 0)

        return ret;

    /* extradata will contain every chunk up to the first fcTL (excluded) */

    ctx->extra_data = av_malloc(len + 12 + AV_INPUT_BUFFER_PADDING_SIZE);

    if (!ctx->extra_data)

        return AVERROR(ENOMEM);

    ctx->extra_data_size = len + 12;

    AV_WB32(ctx->extra_data,    len);

    AV_WL32(ctx->extra_data+4,  tag);

    AV_WB32(ctx->extra_data+8,  st->codecpar->width);

    AV_WB32(ctx->extra_data+12, st->codecpar->height);

    if ((ret = avio_read(pb, ctx->extra_data+16, 9)) < 0)

        goto fail;

    while (!avio_feof(pb)) {

        if (acTL_found && ctx->num_play != 1) {

            int64_t size   = avio_size(pb);

            int64_t offset = avio_tell(pb);

            if (size < 0) {

                ret = size;

                goto fail;

            } else if (offset < 0) {

                ret = offset;

                goto fail;

            } else if ((ret = ffio_ensure_seekback(pb, size - offset)) < 0) {

                av_log(s, AV_LOG_WARNING, "Could not ensure seekback, will not loop\n");

                ctx->num_play = 1;

            }

        }

        if ((ctx->num_play == 1 || !acTL_found) &&

            ((ret = ffio_ensure_seekback(pb, 4 /* len */ + 4 /* tag */)) < 0))

            goto fail;

        len = avio_rb32(pb);

        if (len > 0x7fffffff) {

            ret = AVERROR_INVALIDDATA;

            goto fail;

        }

        tag = avio_rl32(pb);

        switch (tag) {

        case MKTAG('a', 'c', 'T', 'L'):

            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||

                (ret = append_extradata(ctx, pb, len + 12)) < 0)

                goto fail;

            acTL_found = 1;

            ctx->num_frames = AV_RB32(ctx->extra_data + ret + 8);

            ctx->num_play   = AV_RB32(ctx->extra_data + ret + 12);

            av_log(s, AV_LOG_DEBUG, "num_frames: %"PRIu32", num_play: %"PRIu32"\n",

                                    ctx->num_frames, ctx->num_play);

            break;

        case MKTAG('f', 'c', 'T', 'L'):

            if (!acTL_found) {

               ret = AVERROR_INVALIDDATA;

               goto fail;

            }

            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0)

                goto fail;

            return 0;

        default:

            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||

                (ret = append_extradata(ctx, pb, len + 12)) < 0)

                goto fail;

        }

    }

fail:

    if (ctx->extra_data_size) {

        av_freep(&ctx->extra_data);

        ctx->extra_data_size = 0;

    }

    return ret;

}


static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)

{

    char *buffer;

    int ret;

    char *path = fs_path->data;

    buffer = rpath(s, path);

    ret = statfs(buffer, stbuf);

    g_free(buffer);

    return ret;

}


int av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4],

                        enum AVPixelFormat pix_fmt, enum AVColorRange range,

                        int width, int height)

{

    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);

    int nb_planes = av_pix_fmt_count_planes(pix_fmt);

    // A pixel or a group of pixels on each plane, with a value that represents black.

    // Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases.

    uint8_t clear_block[4][MAX_BLOCK_SIZE] = {0}; // clear padding with 0

    int clear_block_size[4] = {0};

    ptrdiff_t plane_line_bytes[4] = {0};

    int rgb, limited;

    int plane, c;

    if (!desc || nb_planes < 1 || nb_planes > 4 || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)

        return AVERROR(EINVAL);

    rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB);

    limited = !rgb && range != AVCOL_RANGE_JPEG;

    if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) {

        ptrdiff_t bytewidth = av_image_get_linesize(pix_fmt, width, 0);

        uint8_t *data;

        int mono = pix_fmt == AV_PIX_FMT_MONOWHITE || pix_fmt == AV_PIX_FMT_MONOBLACK;

        int fill = pix_fmt == AV_PIX_FMT_MONOWHITE ? 0xFF : 0;

        if (nb_planes != 1 || !(rgb || mono) || bytewidth < 1)

            return AVERROR(EINVAL);

        if (!dst_data)

            return 0;

        data = dst_data[0];

        // (Bitstream + alpha will be handled incorrectly - it'll remain transparent.)

        for (;height > 0; height--) {

            memset(data, fill, bytewidth);

            data += dst_linesize[0];

        }

        return 0;

    }

    for (c = 0; c < desc->nb_components; c++) {

        const AVComponentDescriptor comp = desc->comp[c];

        // We try to operate on entire non-subsampled pixel groups (for

        // AV_PIX_FMT_UYVY422 this would mean two consecutive pixels).

        clear_block_size[comp.plane] = FFMAX(clear_block_size[comp.plane], comp.step);

        if (clear_block_size[comp.plane] > MAX_BLOCK_SIZE)

            return AVERROR(EINVAL);

    }

    // Create a byte array for clearing 1 pixel (sometimes several pixels).

    for (c = 0; c < desc->nb_components; c++) {

        const AVComponentDescriptor comp = desc->comp[c];

        // (Multiple pixels happen e.g. with AV_PIX_FMT_UYVY422.)

        int w = clear_block_size[comp.plane] / comp.step;

        uint8_t *c_data[4];

        const int c_linesize[4] = {0};

        uint16_t src_array[MAX_BLOCK_SIZE];

        uint16_t src = 0;

        int x;

        if (comp.depth > 16)

            return AVERROR(EINVAL);

        if (!rgb && comp.depth < 8)

            return AVERROR(EINVAL);

        if (w < 1)

            return AVERROR(EINVAL);

        if (c == 0 && limited) {

            src = 16 << (comp.depth - 8);

        } else if ((c == 1 || c == 2) && !rgb) {

            src = 128 << (comp.depth - 8);

        } else if (c == 3) {

            // (Assume even limited YUV uses full range alpha.)

            src = (1 << comp.depth) - 1;

        }

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

            src_array[x] = src;

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

            c_data[x] = &clear_block[x][0];

        av_write_image_line(src_array, c_data, c_linesize, desc, 0, 0, c, w);

    }

    for (plane = 0; plane < nb_planes; plane++) {

        plane_line_bytes[plane] = av_image_get_linesize(pix_fmt, width, plane);

        if (plane_line_bytes[plane] < 0)

            return AVERROR(EINVAL);

    }

    if (!dst_data)

        return 0;

    for (plane = 0; plane < nb_planes; plane++) {

        size_t bytewidth = plane_line_bytes[plane];

        uint8_t *data = dst_data[plane];

        int chroma_div = plane == 1 || plane == 2 ? desc->log2_chroma_h : 0;

        int plane_h = ((height + ( 1 << chroma_div) - 1)) >> chroma_div;

        for (; plane_h > 0; plane_h--) {

            memset_bytes(data, bytewidth, &clear_block[plane][0], clear_block_size[plane]);

            data += dst_linesize[plane];

        }

    }

    return 0;

}


bool cache_is_cached(const PageCache *cache, uint64_t addr)

{

    size_t pos;

    g_assert(cache);

    g_assert(cache->page_cache);

    pos = cache_get_cache_pos(cache, addr);

    return (cache->page_cache[pos].it_addr == addr);

}


static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data,

                                  unsigned size)

{

    int can_write;

    SuperIOConfig *superio_conf = opaque;

    DPRINTF("superio_ioport_writeb  address 0x%x  val 0x%x\n", addr, data);

    if (addr == 0x3f0) {

        superio_conf->index = data & 0xff;

    } else {

        /* 0x3f1 */

        switch (superio_conf->index) {

        case 0x00 ... 0xdf:

        case 0xe4:

        case 0xe5:

        case 0xe9 ... 0xed:

        case 0xf3:

        case 0xf5:

        case 0xf7:

        case 0xf9 ... 0xfb:

        case 0xfd ... 0xff:

            can_write = 0;

            break;

        default:

            can_write = 1;

            if (can_write) {

                switch (superio_conf->index) {

                case 0xe7:

                    if ((data & 0xff) != 0xfe) {

                        DPRINTF("chage uart 1 base. unsupported yet\n");

                    }

                    break;

                case 0xe8:

                    if ((data & 0xff) != 0xbe) {

                        DPRINTF("chage uart 2 base. unsupported yet\n");

                    }

                    break;

                default:

                    superio_conf->config[superio_conf->index] = data & 0xff;

                }

            }

        }

        superio_conf->config[superio_conf->index] = data & 0xff;

    }

}


static int default_fdset_get_fd(int64_t fdset_id, int flags)

{

    return -1;

}


static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)

{

    req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;

    virtio_scsi_complete_cmd_req(req);

}


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

                      Error **errp)

{

    IscsiLun *iscsilun = bs->opaque;

    struct iscsi_context *iscsi = NULL;

    struct iscsi_url *iscsi_url = NULL;

    struct scsi_task *task = NULL;

    struct scsi_inquiry_standard *inq = NULL;

    struct scsi_inquiry_supported_pages *inq_vpd;

    char *initiator_name = NULL;

    QemuOpts *opts;

    Error *local_err = NULL;

    const char *filename;

    int i, ret = 0;

    if ((BDRV_SECTOR_SIZE % 512) != 0) {

        error_setg(errp, "iSCSI: Invalid BDRV_SECTOR_SIZE. "

                   "BDRV_SECTOR_SIZE(%lld) is not a multiple "

                   "of 512", BDRV_SECTOR_SIZE);

        return -EINVAL;

    }

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

    qemu_opts_absorb_qdict(opts, options, &local_err);

    if (local_err) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }

    filename = qemu_opt_get(opts, "filename");

    iscsi_url = iscsi_parse_full_url(iscsi, filename);

    if (iscsi_url == NULL) {

        error_setg(errp, "Failed to parse URL : %s", filename);

        ret = -EINVAL;

        goto out;

    }

    memset(iscsilun, 0, sizeof(IscsiLun));

    initiator_name = parse_initiator_name(iscsi_url->target);

    iscsi = iscsi_create_context(initiator_name);

    if (iscsi == NULL) {

        error_setg(errp, "iSCSI: Failed to create iSCSI context.");

        ret = -ENOMEM;

        goto out;

    }

    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {

        error_setg(errp, "iSCSI: Failed to set target name.");

        ret = -EINVAL;

        goto out;

    }

    if (iscsi_url->user != NULL) {

        ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user,

                                              iscsi_url->passwd);

        if (ret != 0) {

            error_setg(errp, "Failed to set initiator username and password");

            ret = -EINVAL;

            goto out;

        }

    }

    /* check if we got CHAP username/password via the options */

    parse_chap(iscsi, iscsi_url->target, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }

    if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {

        error_setg(errp, "iSCSI: Failed to set session type to normal.");

        ret = -EINVAL;

        goto out;

    }

    iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);

    /* check if we got HEADER_DIGEST via the options */

    parse_header_digest(iscsi, iscsi_url->target, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }

    if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) {

        error_setg(errp, "iSCSI: Failed to connect to LUN : %s",

            iscsi_get_error(iscsi));

        ret = -EINVAL;

        goto out;

    }

    iscsilun->iscsi = iscsi;

    iscsilun->aio_context = bdrv_get_aio_context(bs);

    iscsilun->lun   = iscsi_url->lun;

    iscsilun->has_write_same = true;

    task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 0, 0,

                            (void **) &inq, errp);

    if (task == NULL) {

        ret = -EINVAL;

        goto out;

    }

    iscsilun->type = inq->periperal_device_type;

    scsi_free_scsi_task(task);

    task = NULL;

    /* Check the write protect flag of the LUN if we want to write */

    if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&

        iscsi_is_write_protected(iscsilun)) {

        error_setg(errp, "Cannot open a write protected LUN as read-write");

        ret = -EACCES;

        goto out;

    }

    iscsi_readcapacity_sync(iscsilun, &local_err);

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }

    bs->total_sectors = sector_lun2qemu(iscsilun->num_blocks, iscsilun);

    bs->request_alignment = iscsilun->block_size;

    /* We don't have any emulation for devices other than disks and CD-ROMs, so

     * this must be sg ioctl compatible. We force it to be sg, otherwise qemu

     * will try to read from the device to guess the image format.

     */

    if (iscsilun->type != TYPE_DISK && iscsilun->type != TYPE_ROM) {

        bs->sg = 1;

    }

    task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                            SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES,

                            (void **) &inq_vpd, errp);

    if (task == NULL) {

        ret = -EINVAL;

        goto out;

    }

    for (i = 0; i < inq_vpd->num_pages; i++) {

        struct scsi_task *inq_task;

        struct scsi_inquiry_logical_block_provisioning *inq_lbp;

        struct scsi_inquiry_block_limits *inq_bl;

        switch (inq_vpd->pages[i]) {

        case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:

            inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                                        SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,

                                        (void **) &inq_lbp, errp);

            if (inq_task == NULL) {

                ret = -EINVAL;

                goto out;

            }

            memcpy(&iscsilun->lbp, inq_lbp,

                   sizeof(struct scsi_inquiry_logical_block_provisioning));

            scsi_free_scsi_task(inq_task);

            break;

        case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:

            inq_task = iscsi_do_inquiry(iscsilun->iscsi, iscsilun->lun, 1,

                                    SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,

                                    (void **) &inq_bl, errp);

            if (inq_task == NULL) {

                ret = -EINVAL;

                goto out;

            }

            memcpy(&iscsilun->bl, inq_bl,

                   sizeof(struct scsi_inquiry_block_limits));

            scsi_free_scsi_task(inq_task);

            break;

        default:

            break;

        }

    }

    scsi_free_scsi_task(task);

    task = NULL;

    iscsi_attach_aio_context(bs, iscsilun->aio_context);

    /* Guess the internal cluster (page) size of the iscsi target by the means

     * of opt_unmap_gran. Transfer the unmap granularity only if it has a

     * reasonable size */

    if (iscsilun->bl.opt_unmap_gran * iscsilun->block_size >= 4 * 1024 &&

        iscsilun->bl.opt_unmap_gran * iscsilun->block_size <= 16 * 1024 * 1024) {

        iscsilun->cluster_sectors = (iscsilun->bl.opt_unmap_gran *

                                     iscsilun->block_size) >> BDRV_SECTOR_BITS;

        if (iscsilun->lbprz && !(bs->open_flags & BDRV_O_NOCACHE)) {

            iscsilun->allocationmap = iscsi_allocationmap_init(iscsilun);

            if (iscsilun->allocationmap == NULL) {

                ret = -ENOMEM;

            }

        }

    }

out:

    qemu_opts_del(opts);

    g_free(initiator_name);

    if (iscsi_url != NULL) {

        iscsi_destroy_url(iscsi_url);

    }

    if (task != NULL) {

        scsi_free_scsi_task(task);

    }

    if (ret) {

        if (iscsi != NULL) {

            iscsi_destroy_context(iscsi);

        }

        memset(iscsilun, 0, sizeof(IscsiLun));

    }

    return ret;

}


static void string_output_append_range(StringOutputVisitor *sov,

                                       int64_t s, int64_t e)

{

    Range *r = g_malloc0(sizeof(*r));

    r->begin = s;

    r->end = e + 1;

    sov->ranges = range_list_insert(sov->ranges, r);

}


static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,

                                       int64_t sector_num, int nb_sectors,

                                       QEMUIOVector *iov)

{

    IscsiLun *iscsilun = bs->opaque;

    struct IscsiTask iTask;

    uint64_t lba;

    uint32_t num_sectors;

    if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {

        return -EINVAL;

    }

    if (bs->bl.max_transfer &&

        nb_sectors << BDRV_SECTOR_BITS > bs->bl.max_transfer) {

        error_report("iSCSI Error: Read of %d sectors exceeds max_xfer_len "

                     "of %" PRIu32 " bytes", nb_sectors, bs->bl.max_transfer);

        return -EINVAL;

    }

    if (iscsilun->lbprz && nb_sectors >= ISCSI_CHECKALLOC_THRES &&

        !iscsi_allocationmap_is_allocated(iscsilun, sector_num, nb_sectors)) {

        int64_t ret;

        int pnum;

        BlockDriverState *file;

        ret = iscsi_co_get_block_status(bs, sector_num,

                                        BDRV_REQUEST_MAX_SECTORS, &pnum, &file);

        if (ret < 0) {

            return ret;

        }

        if (ret & BDRV_BLOCK_ZERO && pnum >= nb_sectors) {

            qemu_iovec_memset(iov, 0, 0x00, iov->size);

            return 0;

        }

    }

    lba = sector_qemu2lun(sector_num, iscsilun);

    num_sectors = sector_qemu2lun(nb_sectors, iscsilun);

    iscsi_co_init_iscsitask(iscsilun, &iTask);

retry:

    if (iscsilun->use_16_for_rw) {

        iTask.task = iscsi_read16_task(iscsilun->iscsi, iscsilun->lun, lba,

                                       num_sectors * iscsilun->block_size,

                                       iscsilun->block_size, 0, 0, 0, 0, 0,

                                       iscsi_co_generic_cb, &iTask);

    } else {

        iTask.task = iscsi_read10_task(iscsilun->iscsi, iscsilun->lun, lba,

                                       num_sectors * iscsilun->block_size,

                                       iscsilun->block_size,

                                       0, 0, 0, 0, 0,

                                       iscsi_co_generic_cb, &iTask);

    }

    if (iTask.task == NULL) {

        return -ENOMEM;

    }

    scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov, iov->niov);

    while (!iTask.complete) {

        iscsi_set_events(iscsilun);

        qemu_coroutine_yield();

    }

    if (iTask.task != NULL) {

        scsi_free_scsi_task(iTask.task);

        iTask.task = NULL;

    }

    if (iTask.do_retry) {

        iTask.complete = 0;

        goto retry;

    }

    if (iTask.status != SCSI_STATUS_GOOD) {

        return iTask.err_code;

    }

    return 0;

}


static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)

{

    ObjectClass *oc;

    DeviceClass *dc;

    oc = object_class_by_name(*driver);

    if (!oc) {

        const char *typename = find_typename_by_alias(*driver);

        if (typename) {

            *driver = typename;

            oc = object_class_by_name(*driver);

        }

    }

    if (!object_class_dynamic_cast(oc, TYPE_DEVICE)) {

        error_setg(errp, "'%s' is not a valid device model name", *driver);

        return NULL;

    }

    if (object_class_is_abstract(oc)) {

        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",

                   "non-abstract device type");

        return NULL;

    }

    dc = DEVICE_CLASS(oc);

    if (dc->cannot_instantiate_with_device_add_yet ||

        (qdev_hotplug && !dc->hotpluggable)) {

        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",

                   "pluggable device type");

        return NULL;

    }

    return dc;

}


static int usb_net_handle_control(USBDevice *dev, int request, int value,

                int index, int length, uint8_t *data)

{

    USBNetState *s = (USBNetState *) dev;

    int ret = 0;

    switch(request) {

    case DeviceRequest | USB_REQ_GET_STATUS:

        data[0] = (1 << USB_DEVICE_SELF_POWERED) |

                (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);

        data[1] = 0x00;

        ret = 2;

        break;

    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:

        if (value == USB_DEVICE_REMOTE_WAKEUP) {

            dev->remote_wakeup = 0;

        } else {

            goto fail;

        }

        ret = 0;

        break;

    case DeviceOutRequest | USB_REQ_SET_FEATURE:

        if (value == USB_DEVICE_REMOTE_WAKEUP) {

            dev->remote_wakeup = 1;

        } else {

            goto fail;

        }

        ret = 0;

        break;

    case DeviceOutRequest | USB_REQ_SET_ADDRESS:

        dev->addr = value;

        ret = 0;

        break;

    case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:

        if (!s->rndis || value || index != 0)

            goto fail;

#ifdef TRAFFIC_DEBUG

        {

            unsigned int i;

            fprintf(stderr, "SEND_ENCAPSULATED_COMMAND:");

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

                if (!(i & 15))

                    fprintf(stderr, "\n%04x:", i);

                fprintf(stderr, " %02x", data[i]);

            }

            fprintf(stderr, "\n\n");

        }

#endif

        ret = rndis_parse(s, data, length);

        break;

    case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:

        if (!s->rndis || value || index != 0)

            goto fail;

        ret = rndis_get_response(s, data);

        if (!ret) {

            data[0] = 0;

            ret = 1;

        }

#ifdef TRAFFIC_DEBUG

        {

            unsigned int i;

            fprintf(stderr, "GET_ENCAPSULATED_RESPONSE:");

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

                if (!(i & 15))

                    fprintf(stderr, "\n%04x:", i);

                fprintf(stderr, " %02x", data[i]);

            }

            fprintf(stderr, "\n\n");

        }

#endif

        break;

    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:

        switch(value >> 8) {

        case USB_DT_DEVICE:

            ret = sizeof(qemu_net_dev_descriptor);

            memcpy(data, qemu_net_dev_descriptor, ret);

            break;

        case USB_DT_CONFIG:

            switch (value & 0xff) {

            case 0:

                ret = sizeof(qemu_net_rndis_config_descriptor);

                memcpy(data, qemu_net_rndis_config_descriptor, ret);

                break;

            case 1:

                ret = sizeof(qemu_net_cdc_config_descriptor);

                memcpy(data, qemu_net_cdc_config_descriptor, ret);

                break;

            default:

                goto fail;

            }

            data[2] = ret & 0xff;

            data[3] = ret >> 8;

            break;

        case USB_DT_STRING:

            switch (value & 0xff) {

            case 0:

                /* language ids */

                data[0] = 4;

                data[1] = 3;

                data[2] = 0x09;

                data[3] = 0x04;

                ret = 4;

                break;

            case STRING_ETHADDR:

                ret = set_usb_string(data, s->usbstring_mac);

                break;

            default:

                if (usb_net_stringtable[value & 0xff]) {

                    ret = set_usb_string(data,

                                    usb_net_stringtable[value & 0xff]);

                    break;

                }

                goto fail;

            }

            break;

        default:

            goto fail;

        }

        break;

    case DeviceRequest | USB_REQ_GET_CONFIGURATION:

        data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;

        ret = 1;

        break;

    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:

        switch (value & 0xff) {

        case DEV_CONFIG_VALUE:

            s->rndis = 0;

            break;

        case DEV_RNDIS_CONFIG_VALUE:

            s->rndis = 1;

            break;

        default:

            goto fail;

        }

        ret = 0;

        break;

    case DeviceRequest | USB_REQ_GET_INTERFACE:

    case InterfaceRequest | USB_REQ_GET_INTERFACE:

        data[0] = 0;

        ret = 1;

        break;

    case DeviceOutRequest | USB_REQ_SET_INTERFACE:

    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:

        ret = 0;

        break;

    default:

    fail:

        fprintf(stderr, "usbnet: failed control transaction: "

                        "request 0x%x value 0x%x index 0x%x length 0x%x\n",

                        request, value, index, length);

        ret = USB_RET_STALL;

        break;

    }

    return ret;

}


static void v9fs_synth_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)

{

    v9fs_synth_seekdir(ctx, fs, 0);

}


void ff_vp3_h_loop_filter_c(uint8_t *first_pixel, int stride, int *bounding_values)

{

    unsigned char *end;

    int filter_value;

    for (end= first_pixel + 8*stride; first_pixel != end; first_pixel += stride) {

        filter_value =

            (first_pixel[-2] - first_pixel[ 1])

         +3*(first_pixel[ 0] - first_pixel[-1]);

        filter_value = bounding_values[(filter_value + 4) >> 3];

        first_pixel[-1] = av_clip_uint8(first_pixel[-1] + filter_value);

        first_pixel[ 0] = av_clip_uint8(first_pixel[ 0] - filter_value);

    }

}


static int huffman_decode(MPADecodeContext *s, GranuleDef *g,

                          int16_t *exponents, int end_pos2)

{

    int s_index;

    int i;

    int last_pos, bits_left;

    VLC *vlc;

    int end_pos = FFMIN(end_pos2, s->gb.size_in_bits);

    /* low frequencies (called big values) */

    s_index = 0;

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

        int j, k, l, linbits;

        j = g->region_size[i];

        if (j == 0)

            continue;

        /* select vlc table */

        k       = g->table_select[i];

        l       = mpa_huff_data[k][0];

        linbits = mpa_huff_data[k][1];

        vlc     = &huff_vlc[l];

        if (!l) {

            memset(&g->sb_hybrid[s_index], 0, sizeof(*g->sb_hybrid) * 2 * j);

            s_index += 2 * j;

            continue;

        }

        /* read huffcode and compute each couple */

        for (; j > 0; j--) {

            int exponent, x, y;

            int v;

            int pos = get_bits_count(&s->gb);

            if (pos >= end_pos){

//                av_log(NULL, AV_LOG_ERROR, "pos: %d %d %d %d\n", pos, end_pos, end_pos2, s_index);

                switch_buffer(s, &pos, &end_pos, &end_pos2);

//                av_log(NULL, AV_LOG_ERROR, "new pos: %d %d\n", pos, end_pos);

                if (pos >= end_pos)

                    break;

            }

            y = get_vlc2(&s->gb, vlc->table, 7, 3);

            if (!y) {

                g->sb_hybrid[s_index  ] =

                g->sb_hybrid[s_index+1] = 0;

                s_index += 2;

                continue;

            }

            exponent= exponents[s_index];

            av_dlog(s->avctx, "region=%d n=%d x=%d y=%d exp=%d\n",

                    i, g->region_size[i] - j, x, y, exponent);

            if (y & 16) {

                x = y >> 5;

                y = y & 0x0f;

                if (x < 15) {

                    READ_FLIP_SIGN(g->sb_hybrid + s_index, RENAME(expval_table)[exponent] + x)

                } else {

                    x += get_bitsz(&s->gb, linbits);

                    v  = l3_unscale(x, exponent);

                    if (get_bits1(&s->gb))

                        v = -v;

                    g->sb_hybrid[s_index] = v;

                }

                if (y < 15) {

                    READ_FLIP_SIGN(g->sb_hybrid + s_index + 1, RENAME(expval_table)[exponent] + y)

                } else {

                    y += get_bitsz(&s->gb, linbits);

                    v  = l3_unscale(y, exponent);

                    if (get_bits1(&s->gb))

                        v = -v;

                    g->sb_hybrid[s_index+1] = v;

                }

            } else {

                x = y >> 5;

                y = y & 0x0f;

                x += y;

                if (x < 15) {

                    READ_FLIP_SIGN(g->sb_hybrid + s_index + !!y, RENAME(expval_table)[exponent] + x)

                } else {

                    x += get_bitsz(&s->gb, linbits);

                    v  = l3_unscale(x, exponent);

                    if (get_bits1(&s->gb))

                        v = -v;

                    g->sb_hybrid[s_index+!!y] = v;

                }

                g->sb_hybrid[s_index + !y] = 0;

            }

            s_index += 2;

        }

    }

    /* high frequencies */

    vlc = &huff_quad_vlc[g->count1table_select];

    last_pos = 0;

    while (s_index <= 572) {

        int pos, code;

        pos = get_bits_count(&s->gb);

        if (pos >= end_pos) {

            if (pos > end_pos2 && last_pos) {

                /* some encoders generate an incorrect size for this

                   part. We must go back into the data */

                s_index -= 4;

                skip_bits_long(&s->gb, last_pos - pos);

                av_log(s->avctx, AV_LOG_INFO, "overread, skip %d enddists: %d %d\n", last_pos - pos, end_pos-pos, end_pos2-pos);

                if(s->err_recognition & AV_EF_BITSTREAM)

                    s_index=0;

                break;

            }

//                av_log(NULL, AV_LOG_ERROR, "pos2: %d %d %d %d\n", pos, end_pos, end_pos2, s_index);

            switch_buffer(s, &pos, &end_pos, &end_pos2);

//                av_log(NULL, AV_LOG_ERROR, "new pos2: %d %d %d\n", pos, end_pos, s_index);

            if (pos >= end_pos)

                break;

        }

        last_pos = pos;

        code = get_vlc2(&s->gb, vlc->table, vlc->bits, 1);

        av_dlog(s->avctx, "t=%d code=%d\n", g->count1table_select, code);

        g->sb_hybrid[s_index+0] =

        g->sb_hybrid[s_index+1] =

        g->sb_hybrid[s_index+2] =

        g->sb_hybrid[s_index+3] = 0;

        while (code) {

            static const int idxtab[16] = { 3,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0 };

            int v;

            int pos = s_index + idxtab[code];

            code   ^= 8 >> idxtab[code];

            READ_FLIP_SIGN(g->sb_hybrid + pos, RENAME(exp_table)+exponents[pos])

        }

        s_index += 4;

    }

    /* skip extension bits */

    bits_left = end_pos2 - get_bits_count(&s->gb);

//av_log(NULL, AV_LOG_ERROR, "left:%d buf:%p\n", bits_left, s->in_gb.buffer);

    if (bits_left < 0 && (s->err_recognition & AV_EF_BITSTREAM)) {

        av_log(s->avctx, AV_LOG_ERROR, "bits_left=%d\n", bits_left);

        s_index=0;

    } else if (bits_left > 0 && (s->err_recognition & AV_EF_BUFFER)) {

        av_log(s->avctx, AV_LOG_ERROR, "bits_left=%d\n", bits_left);

        s_index = 0;

    }

    memset(&g->sb_hybrid[s_index], 0, sizeof(*g->sb_hybrid) * (576 - s_index));

    skip_bits_long(&s->gb, bits_left);

    i = get_bits_count(&s->gb);

    switch_buffer(s, &i, &end_pos, &end_pos2);

    return 0;

}


static void memory_region_write_thunk_n(void *_mr,

                                        target_phys_addr_t addr,

                                        unsigned size,

                                        uint64_t data)

{

    MemoryRegion *mr = _mr;

    if (!memory_region_access_valid(mr, addr, size)) {

        return; /* FIXME: better signalling */

    }

    if (!mr->ops->write) {

        mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);

        return;

    }

    /* FIXME: support unaligned access */

    access_with_adjusted_size(addr + mr->offset, &data, size,

                              mr->ops->impl.min_access_size,

                              mr->ops->impl.max_access_size,

                              memory_region_write_accessor, mr);

}


static int zipl_load_segment(struct component_entry *entry)

{

    const int max_entries = (SECTOR_SIZE / sizeof(struct scsi_blockptr));

    struct scsi_blockptr *bprs = (void*)sec;

    const int bprs_size = sizeof(sec);

    uint64_t blockno;

    long address;

    int i;

    blockno = entry->data.blockno;

    address = entry->load_address;

    debug_print_int("loading segment at block", blockno);

    debug_print_int("addr", address);

    do {

        memset(bprs, FREE_SPACE_FILLER, bprs_size);

        if (virtio_read(blockno, (uint8_t *)bprs)) {

            debug_print_int("failed reading bprs at", blockno);

            goto fail;

        }

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

            u64 *cur_desc = (void*)&bprs[i];

            blockno = bprs[i].blockno;

            if (!blockno)

                break;

            /* we need the updated blockno for the next indirect entry in the

               chain, but don't want to advance address */

            if (i == (max_entries - 1))

                break;

            if (bprs[i].blockct == 0 && unused_space(&bprs[i + 1],

                sizeof(struct scsi_blockptr))) {

                /* This is a "continue" pointer.

                 * This ptr is the last one in the current script section.

                 * I.e. the next ptr must point to the unused memory area.

                 * The blockno is not zero, so the upper loop must continue

                 * reading next section of BPRS.

                 */

                break;

            }

            address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,

                                         (void*)address);

            if (address == -1)

                goto fail;

        }

    } while (blockno);

    return 0;

fail:

    sclp_print("failed loading segment\n");

    return -1;

}


int event_notifier_set(EventNotifier *e)

{

    uint64_t value = 1;

    int r = write(e->fd, &value, sizeof(value));

    return r == sizeof(value);

}


long do_sigreturn(CPUSPARCState *env)

{

    abi_ulong sf_addr;

    struct target_signal_frame *sf;

    uint32_t up_psr, pc, npc;

    target_sigset_t set;

    sigset_t host_set;

    int err=0, i;

    sf_addr = env->regwptr[UREG_FP];

    trace_user_do_sigreturn(env, sf_addr);

    if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {

        goto segv_and_exit;

    }

    /* 1. Make sure we are not getting garbage from the user */

    if (sf_addr & 3)

        goto segv_and_exit;

    __get_user(pc,  &sf->info.si_regs.pc);

    __get_user(npc, &sf->info.si_regs.npc);

    if ((pc | npc) & 3) {

        goto segv_and_exit;

    }

    /* 2. Restore the state */

    __get_user(up_psr, &sf->info.si_regs.psr);

    /* User can only change condition codes and FPU enabling in %psr. */

    env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))

            | (env->psr & ~(PSR_ICC /* | PSR_EF */));

    env->pc = pc;

    env->npc = npc;

    __get_user(env->y, &sf->info.si_regs.y);

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

        __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);

    }

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

        __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);

    }

    /* FIXME: implement FPU save/restore:

         * __get_user(fpu_save, &sf->fpu_save);

         * if (fpu_save)

         *        err |= restore_fpu_state(env, fpu_save);

         */

    /* This is pretty much atomic, no amount locking would prevent

         * the races which exist anyways.

         */

    __get_user(set.sig[0], &sf->info.si_mask);

    for(i = 1; i < TARGET_NSIG_WORDS; i++) {

        __get_user(set.sig[i], &sf->extramask[i - 1]);

    }

    target_to_host_sigset_internal(&host_set, &set);

    do_sigprocmask(SIG_SETMASK, &host_set, NULL);

    if (err) {

        goto segv_and_exit;

    }

    unlock_user_struct(sf, sf_addr, 0);

    return env->regwptr[0];

segv_and_exit:

    unlock_user_struct(sf, sf_addr, 0);

    force_sig(TARGET_SIGSEGV);

}


void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry,

                             int nb_clusters, enum qcow2_discard_type type)

{

    BDRVQcow2State *s = bs->opaque;

    switch (qcow2_get_cluster_type(l2_entry)) {

    case QCOW2_CLUSTER_COMPRESSED:

        {

            int nb_csectors;

            nb_csectors = ((l2_entry >> s->csize_shift) &

                           s->csize_mask) + 1;

            qcow2_free_clusters(bs,

                (l2_entry & s->cluster_offset_mask) & ~511,

                nb_csectors * 512, type);

        }

        break;

    case QCOW2_CLUSTER_NORMAL:

    case QCOW2_CLUSTER_ZERO:

        if (l2_entry & L2E_OFFSET_MASK) {

            if (offset_into_cluster(s, l2_entry & L2E_OFFSET_MASK)) {

                qcow2_signal_corruption(bs, false, -1, -1,

                                        "Cannot free unaligned cluster %#llx",

                                        l2_entry & L2E_OFFSET_MASK);

            } else {

                qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK,

                                    nb_clusters << s->cluster_bits, type);

            }

        }

        break;

    case QCOW2_CLUSTER_UNALLOCATED:

        break;

    default:

        abort();

    }

}


void qemu_put_byte(QEMUFile *f, int v)

{

    if (!f->last_error && f->is_write == 0 && f->buf_index > 0) {

        fprintf(stderr,

                "Attempted to write to buffer while read buffer is not empty\n");

        abort();

    }

    f->buf[f->buf_index++] = v;

    f->is_write = 1;

    if (f->buf_index >= IO_BUF_SIZE) {

        int ret = qemu_fflush(f);

        qemu_file_set_if_error(f, ret);

    }

}


static void n8x0_i2c_setup(struct n800_s *s)

{

    DeviceState *dev;

    qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);

    /* Attach the CPU on one end of our I2C bus.  */

    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);

    /* Attach a menelaus PM chip */

    dev = i2c_create_slave(s->i2c, "twl92230", N8X0_MENELAUS_ADDR);

    qdev_connect_gpio_out(dev, 3, s->cpu->irq[0][OMAP_INT_24XX_SYS_NIRQ]);

    /* Attach a TMP105 PM chip (A0 wired to ground) */

    dev = i2c_create_slave(s->i2c, "tmp105", N8X0_TMP105_ADDR);

    qdev_connect_gpio_out(dev, 0, tmp_irq);

}


void destroy_bdrvs(dev_match_fn *match_fn, void *arg)

{

    DriveInfo *dinfo;

    struct BlockDriverState *bs;

    TAILQ_FOREACH(dinfo, &drives, next) {

        bs = dinfo->bdrv;

        if (bs) {

            if (bs->private && match_fn(bs->private, arg)) {

                drive_uninit(bs);

                bdrv_delete(bs);

            }

        }

    }

}


TranslationBlock *tb_gen_code(CPUState *cpu,

                              target_ulong pc, target_ulong cs_base,

                              int flags, int cflags)

{

    CPUArchState *env = cpu->env_ptr;

    TranslationBlock *tb;

    tb_page_addr_t phys_pc, phys_page2;

    target_ulong virt_page2;

    tcg_insn_unit *gen_code_buf;

    int gen_code_size, search_size;

#ifdef CONFIG_PROFILER

    int64_t ti;

#endif

    phys_pc = get_page_addr_code(env, pc);

    if (use_icount) {

        cflags |= CF_USE_ICOUNT;

    }

    tb = tb_alloc(pc);

    if (unlikely(!tb)) {

 buffer_overflow:

        /* flush must be done */

        tb_flush(cpu);

        /* cannot fail at this point */

        tb = tb_alloc(pc);

        assert(tb != NULL);

        /* Don't forget to invalidate previous TB info.  */

        tcg_ctx.tb_ctx.tb_invalidated_flag = 1;

    }

    gen_code_buf = tcg_ctx.code_gen_ptr;

    tb->tc_ptr = gen_code_buf;

    tb->cs_base = cs_base;

    tb->flags = flags;

    tb->cflags = cflags;

#ifdef CONFIG_PROFILER

    tcg_ctx.tb_count1++; /* includes aborted translations because of

                       exceptions */

    ti = profile_getclock();

#endif

    tcg_func_start(&tcg_ctx);

    gen_intermediate_code(env, tb);

    trace_translate_block(tb, tb->pc, tb->tc_ptr);

    /* generate machine code */

    tb->tb_next_offset[0] = 0xffff;

    tb->tb_next_offset[1] = 0xffff;

    tcg_ctx.tb_next_offset = tb->tb_next_offset;

#ifdef USE_DIRECT_JUMP

    tcg_ctx.tb_jmp_offset = tb->tb_jmp_offset;

    tcg_ctx.tb_next = NULL;

#else

    tcg_ctx.tb_jmp_offset = NULL;

    tcg_ctx.tb_next = tb->tb_next;

#endif

#ifdef CONFIG_PROFILER

    tcg_ctx.tb_count++;

    tcg_ctx.interm_time += profile_getclock() - ti;

    tcg_ctx.code_time -= profile_getclock();

#endif

    /* ??? Overflow could be handled better here.  In particular, we

       don't need to re-do gen_intermediate_code, nor should we re-do

       the tcg optimization currently hidden inside tcg_gen_code.  All

       that should be required is to flush the TBs, allocate a new TB,

       re-initialize it per above, and re-do the actual code generation.  */

    gen_code_size = tcg_gen_code(&tcg_ctx, gen_code_buf);

    if (unlikely(gen_code_size < 0)) {

        goto buffer_overflow;

    }

    search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);

    if (unlikely(search_size < 0)) {

        goto buffer_overflow;

    }

#ifdef CONFIG_PROFILER

    tcg_ctx.code_time += profile_getclock();

    tcg_ctx.code_in_len += tb->size;

    tcg_ctx.code_out_len += gen_code_size;

    tcg_ctx.search_out_len += search_size;

#endif

#ifdef DEBUG_DISAS

    if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {

        qemu_log("OUT: [size=%d]\n", gen_code_size);

        log_disas(tb->tc_ptr, gen_code_size);

        qemu_log("\n");

        qemu_log_flush();

    }

#endif

    tcg_ctx.code_gen_ptr = (void *)

        ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size,

                 CODE_GEN_ALIGN);

    /* check next page if needed */

    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;

    phys_page2 = -1;

    if ((pc & TARGET_PAGE_MASK) != virt_page2) {

        phys_page2 = get_page_addr_code(env, virt_page2);

    }

    tb_link_page(tb, phys_pc, phys_page2);

    return tb;

}


static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)

{

    BlockRequest *blkreq;

    uint64_t sector;

    sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);

    trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);

    if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {

        virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);

        virtio_blk_free_request(req);

        return;

    }

    block_acct_start(bdrv_get_stats(req->dev->bs), &req->acct, req->qiov.size,

                     BLOCK_ACCT_WRITE);

    if (mrb->num_writes == 32) {

        virtio_submit_multiwrite(req->dev->bs, mrb);

    }

    blkreq = &mrb->blkreq[mrb->num_writes];

    blkreq->sector = sector;

    blkreq->nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;

    blkreq->qiov = &req->qiov;

    blkreq->cb = virtio_blk_rw_complete;

    blkreq->opaque = req;

    blkreq->error = 0;

    mrb->num_writes++;

}


static int vc1_parse(AVCodecParserContext *s,

                           AVCodecContext *avctx,

                           const uint8_t **poutbuf, int *poutbuf_size,

                           const uint8_t *buf, int buf_size)

{

    /* Here we do the searching for frame boundaries and headers at

     * the same time. Only a minimal amount at the start of each

     * header is unescaped. */

    VC1ParseContext *vpc = s->priv_data;

    int pic_found = vpc->pc.frame_start_found;

    uint8_t *unesc_buffer = vpc->unesc_buffer;

    size_t unesc_index = vpc->unesc_index;

    VC1ParseSearchState search_state = vpc->search_state;

    int start_code_found;

    int next = END_NOT_FOUND;

    int i = vpc->bytes_to_skip;

    if (pic_found && buf_size == 0) {

        /* EOF considered as end of frame */

        memset(unesc_buffer + unesc_index, 0, UNESCAPED_THRESHOLD - unesc_index);

        vc1_extract_header(s, avctx, unesc_buffer, unesc_index);

        next = 0;

    }

    while (i < buf_size) {

        uint8_t b;

        start_code_found = 0;

        while (i < buf_size && unesc_index < UNESCAPED_THRESHOLD) {

            b = buf[i++];

            unesc_buffer[unesc_index++] = b;

            if (search_state <= ONE_ZERO)

                search_state = b ? NO_MATCH : search_state + 1;

            else if (search_state == TWO_ZEROS) {

                if (b == 1)

                    search_state = ONE;

                else if (b > 1) {

                    if (b == 3)

                        unesc_index--; // swallow emulation prevention byte

                    search_state = NO_MATCH;

                }

            }

            else { // search_state == ONE

                // Header unescaping terminates early due to detection of next start code

                search_state = NO_MATCH;

                start_code_found = 1;

                break;

            }

        }

        if ((s->flags & PARSER_FLAG_COMPLETE_FRAMES) &&

                unesc_index >= UNESCAPED_THRESHOLD &&

                vpc->prev_start_code == (VC1_CODE_FRAME & 0xFF))

        {

            // No need to keep scanning the rest of the buffer for

            // start codes if we know it contains a complete frame and

            // we've already unescaped all we need of the frame header

            vc1_extract_header(s, avctx, unesc_buffer, unesc_index);

            break;

        }

        if (unesc_index >= UNESCAPED_THRESHOLD && !start_code_found) {

            while (i < buf_size) {

                if (search_state == NO_MATCH) {

                    i += vpc->v.vc1dsp.startcode_find_candidate(buf + i, buf_size - i);

                    if (i < buf_size) {

                        search_state = ONE_ZERO;

                    }

                    i++;

                } else {

                    b = buf[i++];

                    if (search_state == ONE_ZERO)

                        search_state = b ? NO_MATCH : TWO_ZEROS;

                    else if (search_state == TWO_ZEROS) {

                        if (b >= 1)

                            search_state = b == 1 ? ONE : NO_MATCH;

                    }

                    else { // search_state == ONE

                        search_state = NO_MATCH;

                        start_code_found = 1;

                        break;

                    }

                }

            }

        }

        if (start_code_found) {

            vc1_extract_header(s, avctx, unesc_buffer, unesc_index);

            vpc->prev_start_code = b;

            unesc_index = 0;

            if (!(s->flags & PARSER_FLAG_COMPLETE_FRAMES)) {

                if (!pic_found && (b == (VC1_CODE_FRAME & 0xFF) || b == (VC1_CODE_FIELD & 0xFF))) {

                    pic_found = 1;

                }

                else if (pic_found && b != (VC1_CODE_FIELD & 0xFF) && b != (VC1_CODE_SLICE & 0xFF)) {

                    next = i - 4;

                    pic_found = b == (VC1_CODE_FRAME & 0xFF);

                    break;

                }

            }

        }

    }

    vpc->pc.frame_start_found = pic_found;

    vpc->unesc_index = unesc_index;

    vpc->search_state = search_state;

    if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {

        next = buf_size;

    } else {

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

            vpc->bytes_to_skip = 0;

            *poutbuf = NULL;

            *poutbuf_size = 0;

            return buf_size;

        }

    }

    /* If we return with a valid pointer to a combined frame buffer

     * then on the next call then we'll have been unhelpfully rewound

     * by up to 4 bytes (depending upon whether the start code

     * overlapped the input buffer, and if so by how much). We don't

     * want this: it will either cause spurious second detections of

     * the start code we've already seen, or cause extra bytes to be

     * inserted at the start of the unescaped buffer. */

    vpc->bytes_to_skip = 4;

    if (next < 0 && start_code_found)

        vpc->bytes_to_skip += next;

    *poutbuf = buf;

    *poutbuf_size = buf_size;

    return next;

}


static void bdrv_co_complete(BlockAIOCBCoroutine *acb)

{

    if (!acb->need_bh) {

        acb->common.cb(acb->common.opaque, acb->req.error);

        qemu_aio_unref(acb);

    }

}


QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)

{

    /* FIXME: we should require that a visit occurred, and that it is

     * complete (no starts without a matching end) */

    QObject *obj = qov->root;

    if (obj) {

        qobject_incref(obj);

    } else {

        obj = qnull();

    }

    return obj;

}


eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords)

{

    /* Add a new EEPROM (with 16, 64 or 256 words). */

    eeprom_t *eeprom;

    uint8_t addrbits;

    switch (nwords) {

        case 16:

        case 64:

            addrbits = 6;

            break;

        case 128:

        case 256:

            addrbits = 8;

            break;

        default:

            assert(!"Unsupported EEPROM size, fallback to 64 words!");

            nwords = 64;

            addrbits = 6;

    }

    eeprom = (eeprom_t *)g_malloc0(sizeof(*eeprom) + nwords * 2);

    eeprom->size = nwords;

    eeprom->addrbits = addrbits;

    /* Output DO is tristate, read results in 1. */

    eeprom->eedo = 1;

    logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);

    vmstate_register(dev, 0, &vmstate_eeprom, eeprom);

    return eeprom;

}


static void cdrom_change_cb(void *opaque)

{

    IDEState *s = opaque;

    uint64_t nb_sectors;

    /* XXX: send interrupt too */

    bdrv_get_geometry(s->bs, &nb_sectors);

    s->nb_sectors = nb_sectors;

}


void *qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)

{

    return (void *)(uintptr_t)addr;

}


static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3,

                  uint64_t x4, uint64_t x5, uint64_t x6)

{

    TraceRecord *rec = &trace_buf[trace_idx];

    if (!trace_list[event].state) {

        return;

    }

    rec->event = event;

    rec->timestamp_ns = get_clock();

    rec->x1 = x1;

    rec->x2 = x2;

    rec->x3 = x3;

    rec->x4 = x4;

    rec->x5 = x5;

    rec->x6 = x6;

    if (++trace_idx == TRACE_BUF_LEN) {

        st_flush_trace_buffer();

    }

}


static void gen_intermediate_code_internal(CPULM32State *env,

        TranslationBlock *tb, int search_pc)

{

    struct DisasContext ctx, *dc = &ctx;

    uint16_t *gen_opc_end;

    uint32_t pc_start;

    int j, lj;

    uint32_t next_page_start;

    int num_insns;

    int max_insns;

    qemu_log_try_set_file(stderr);

    pc_start = tb->pc;

    dc->env = env;

    dc->tb = tb;

    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;

    dc->is_jmp = DISAS_NEXT;

    dc->pc = pc_start;

    dc->singlestep_enabled = env->singlestep_enabled;

    dc->nr_nops = 0;

    if (pc_start & 3) {

        cpu_abort(env, "LM32: unaligned PC=%x\n", pc_start);

    }

    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {

        qemu_log("-----------------------------------------\n");

        log_cpu_state(env, 0);

    }

    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;

    lj = -1;

    num_insns = 0;

    max_insns = tb->cflags & CF_COUNT_MASK;

    if (max_insns == 0) {

        max_insns = CF_COUNT_MASK;

    }

    gen_icount_start();

    do {

        check_breakpoint(env, dc);

        if (search_pc) {

            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;

            if (lj < j) {

                lj++;

                while (lj < j) {

                    tcg_ctx.gen_opc_instr_start[lj++] = 0;

                }

            }

            tcg_ctx.gen_opc_pc[lj] = dc->pc;

            tcg_ctx.gen_opc_instr_start[lj] = 1;

            tcg_ctx.gen_opc_icount[lj] = num_insns;

        }

        /* Pretty disas.  */

        LOG_DIS("%8.8x:\t", dc->pc);

        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {

            gen_io_start();

        }

        decode(dc, cpu_ldl_code(env, dc->pc));

        dc->pc += 4;

        num_insns++;

    } while (!dc->is_jmp

         && tcg_ctx.gen_opc_ptr < gen_opc_end

         && !env->singlestep_enabled

         && !singlestep

         && (dc->pc < next_page_start)

         && num_insns < max_insns);

    if (tb->cflags & CF_LAST_IO) {

        gen_io_end();

    }

    if (unlikely(env->singlestep_enabled)) {

        if (dc->is_jmp == DISAS_NEXT) {

            tcg_gen_movi_tl(cpu_pc, dc->pc);

        }

        t_gen_raise_exception(dc, EXCP_DEBUG);

    } else {

        switch (dc->is_jmp) {

        case DISAS_NEXT:

            gen_goto_tb(dc, 1, dc->pc);

            break;

        default:

        case DISAS_JUMP:

        case DISAS_UPDATE:

            /* indicate that the hash table must be used

               to find the next TB */

            tcg_gen_exit_tb(0);

            break;

        case DISAS_TB_JUMP:

            /* nothing more to generate */

            break;

        }

    }

    gen_icount_end(tb, num_insns);

    *tcg_ctx.gen_opc_ptr = INDEX_op_end;

    if (search_pc) {

        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;

        lj++;

        while (lj <= j) {

            tcg_ctx.gen_opc_instr_start[lj++] = 0;

        }

    } else {

        tb->size = dc->pc - pc_start;

        tb->icount = num_insns;

    }

#ifdef DEBUG_DISAS

    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {

        qemu_log("\n");

        log_target_disas(env, pc_start, dc->pc - pc_start, 0);

        qemu_log("\nisize=%d osize=%td\n",

            dc->pc - pc_start, tcg_ctx.gen_opc_ptr -

            tcg_ctx.gen_opc_buf);

    }

#endif

}


void acpi_gpe_init(ACPIREGS *ar, uint8_t len)

{

    ar->gpe.len = len;

    ar->gpe.sts = g_malloc0(len / 2);

    ar->gpe.en = g_malloc0(len / 2);

}


static void xtensa_cpu_initfn(Object *obj)

{

    CPUState *cs = CPU(obj);

    XtensaCPU *cpu = XTENSA_CPU(obj);

    XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(obj);

    CPUXtensaState *env = &cpu->env;

    static bool tcg_inited;

    cs->env_ptr = env;

    env->config = xcc->config;

    cpu_exec_init(cs, &error_abort);

    if (tcg_enabled() && !tcg_inited) {

        tcg_inited = true;

        xtensa_translate_init();

    }

}


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

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);

    dc->realize = dp8393x_realize;

    dc->reset = dp8393x_reset;

    dc->vmsd = &vmstate_dp8393x;

    dc->props = dp8393x_properties;

}


static int mjpeg_decode_sof0(MJpegDecodeContext *s,

                             UINT8 *buf, int buf_size)

{

    int len, nb_components, i, width, height;

    init_get_bits(&s->gb, buf, buf_size);

    /* XXX: verify len field validity */

    len = get_bits(&s->gb, 16);

    /* only 8 bits/component accepted */

    if (get_bits(&s->gb, 8) != 8)

        return -1;

    height = get_bits(&s->gb, 16);

    width = get_bits(&s->gb, 16);

    nb_components = get_bits(&s->gb, 8);

    if (nb_components <= 0 ||

        nb_components > MAX_COMPONENTS)

        return -1;

    s->nb_components = nb_components;

    s->h_max = 1;

    s->v_max = 1;

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

        /* component id */

        s->component_id[i] = get_bits(&s->gb, 8) - 1;

        s->h_count[i] = get_bits(&s->gb, 4);

        s->v_count[i] = get_bits(&s->gb, 4);

        /* compute hmax and vmax (only used in interleaved case) */

        if (s->h_count[i] > s->h_max)

            s->h_max = s->h_count[i];

        if (s->v_count[i] > s->v_max)

            s->v_max = s->v_count[i];

        s->quant_index[i] = get_bits(&s->gb, 8);

        if (s->quant_index[i] >= 4)

            return -1;

        dprintf("component %d %d:%d\n", i, s->h_count[i], s->v_count[i]);

    }

    /* if different size, realloc/alloc picture */

    /* XXX: also check h_count and v_count */

    if (width != s->width || height != s->height) {

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

            free(s->current_picture[i]);

            s->current_picture[i] = NULL;

        }

        s->width = width;

        s->height = height;

        /* test interlaced mode */

        if (s->first_picture &&

            s->org_height != 0 &&

            s->height < ((s->org_height * 3) / 4)) {

            s->interlaced = 1;

            s->bottom_field = 0;

        }

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

            int w, h;

            w = (s->width  + 8 * s->h_max - 1) / (8 * s->h_max);

            h = (s->height + 8 * s->v_max - 1) / (8 * s->v_max);

            w = w * 8 * s->h_count[i];

            h = h * 8 * s->v_count[i];

            if (s->interlaced)

                w *= 2;

            s->linesize[i] = w;

            /* memory test is done in mjpeg_decode_sos() */

            s->current_picture[i] = av_mallocz(w * h);

        }

        s->first_picture = 0;

    }

    if (len != 8+(3*nb_components))

	dprintf("decode_sof0: error, len(%d) mismatch\n", len);

    return 0;

}


int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)

{

    int ret;

    /* find supported formats from sub-filters, and merge along links */

    if ((ret = query_formats(graph, log_ctx)) < 0)

        return ret;

    /* Once everything is merged, it's possible that we'll still have

     * multiple valid media format choices. We pick the first one. */

    pick_formats(graph);

    return 0;

}


static void avc_luma_midh_qrt_8w_msa(const uint8_t *src, int32_t src_stride,

                                     uint8_t *dst, int32_t dst_stride,

                                     int32_t height, uint8_t horiz_offset)

{

    uint32_t multiple8_cnt;

    for (multiple8_cnt = 2; multiple8_cnt--;) {

        avc_luma_midh_qrt_4w_msa(src, src_stride, dst, dst_stride, height,

                                 horiz_offset);

        src += 4;

        dst += 4;

    }

}


target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1,

                                target_ulong r2, target_ulong r3)

{

    int64_t t1 = extract64(r1, 0, 32);

    int64_t t2 = extract64(r2, 0, 32);

    int64_t t3 = extract64(r3, 0, 32);

    int64_t result;

    result = t2 - (t1 * t3);

    return suov32_neg(env, result);

}


static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)

{

    CharDriverState *chr;

    FDCharDriver *s;

    chr = qemu_chr_alloc();

    s = g_malloc0(sizeof(FDCharDriver));

    s->fd_in = io_channel_from_fd(fd_in);

    s->fd_out = io_channel_from_fd(fd_out);

    qemu_set_nonblock(fd_out);

    s->chr = chr;

    chr->opaque = s;

    chr->chr_add_watch = fd_chr_add_watch;

    chr->chr_write = fd_chr_write;

    chr->chr_update_read_handler = fd_chr_update_read_handler;

    chr->chr_close = fd_chr_close;

    return chr;

}


static void mpeg_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type,

                              int (*mv)[2][4][2], int mb_x, int mb_y,

                              int mb_intra, int mb_skipped)

{

    MpegEncContext *s = opaque;

    s->mv_dir     = mv_dir;

    s->mv_type    = mv_type;

    s->mb_intra   = mb_intra;

    s->mb_skipped = mb_skipped;

    s->mb_x       = mb_x;

    s->mb_y       = mb_y;

    memcpy(s->mv, mv, sizeof(*mv));

    ff_init_block_index(s);

    ff_update_block_index(s);

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

    s->dest[0] = s->current_picture.f->data[0] +

                 s->mb_y * 16 * s->linesize +

                 s->mb_x * 16;

    s->dest[1] = s->current_picture.f->data[1] +

                 s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize +

                 s->mb_x * (16 >> s->chroma_x_shift);

    s->dest[2] = s->current_picture.f->data[2] +

                 s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize +

                 s->mb_x * (16 >> s->chroma_x_shift);

    if (ref)

        av_log(s->avctx, AV_LOG_DEBUG,

               "Interlaced error concealment is not fully implemented\n");

    ff_mpv_reconstruct_mb(s, s->block);

}


static int field_end(H264Context *h, int in_setup)

{

    MpegEncContext *const s     = &h->s;

    AVCodecContext *const avctx = s->avctx;

    int err = 0;

    s->mb_y = 0;

    if (!in_setup && !s->dropable)

        ff_thread_report_progress(&s->current_picture_ptr->f,

                                  (16 * s->mb_height >> FIELD_PICTURE) - 1,

                                  s->picture_structure == PICT_BOTTOM_FIELD);

    if (CONFIG_H264_VDPAU_DECODER &&

        s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)

        ff_vdpau_h264_set_reference_frames(s);

    if (in_setup || !(avctx->active_thread_type & FF_THREAD_FRAME)) {

        if (!s->dropable) {

            err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index);

            h->prev_poc_msb = h->poc_msb;

            h->prev_poc_lsb = h->poc_lsb;

        }

        h->prev_frame_num_offset = h->frame_num_offset;

        h->prev_frame_num        = h->frame_num;

        h->outputed_poc          = h->next_outputed_poc;

    }

    if (avctx->hwaccel) {

        if (avctx->hwaccel->end_frame(avctx) < 0)

            av_log(avctx, AV_LOG_ERROR,

                   "hardware accelerator failed to decode picture\n");

    }

    if (CONFIG_H264_VDPAU_DECODER &&

        s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)

        ff_vdpau_h264_picture_complete(s);

    /*

     * FIXME: Error handling code does not seem to support interlaced

     * when slices span multiple rows

     * The ff_er_add_slice calls don't work right for bottom

     * fields; they cause massive erroneous error concealing

     * Error marking covers both fields (top and bottom).

     * This causes a mismatched s->error_count

     * and a bad error table. Further, the error count goes to

     * INT_MAX when called for bottom field, because mb_y is

     * past end by one (callers fault) and resync_mb_y != 0

     * causes problems for the first MB line, too.

     */

    if (!FIELD_PICTURE)

        ff_er_frame_end(s);

    ff_MPV_frame_end(s);

    h->current_slice = 0;

    return err;

}