static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,

                          int is_right)

{

    int mask = (ot == OT_QUAD ? 0x3f : 0x1f);

    int shift;

    /* load */

    if (op1 == OR_TMP0) {

        gen_op_ld_T0_A0(ot + s->mem_index);

    } else {

        gen_op_mov_TN_reg(ot, 0, op1);

    }

    op2 &= mask;

    if (op2 != 0) {

        switch (ot) {

#ifdef TARGET_X86_64

        case OT_LONG:

            tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);

            if (is_right) {

                tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);

            } else {

                tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);

            }

            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);

            break;

#endif

        default:

            if (is_right) {

                tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], op2);

            } else {

                tcg_gen_rotli_tl(cpu_T[0], cpu_T[0], op2);

            }

            break;

        case OT_BYTE:

            mask = 7;

            goto do_shifts;

        case OT_WORD:

            mask = 15;

        do_shifts:

            shift = op2 & mask;

            if (is_right) {

                shift = mask + 1 - shift;

            }

            gen_extu(ot, cpu_T[0]);

            tcg_gen_shli_tl(cpu_tmp0, cpu_T[0], shift);

            tcg_gen_shri_tl(cpu_T[0], cpu_T[0], mask + 1 - shift);

            tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);

            break;

        }

    }

    /* store */

    if (op1 == OR_TMP0) {

        gen_op_st_T0_A0(ot + s->mem_index);

    } else {

        gen_op_mov_reg_T0(ot, op1);

    }

    if (op2 != 0) {

        /* Compute the flags into CC_SRC.  */

        gen_compute_eflags(s);

        /* The value that was "rotated out" is now present at the other end

           of the word.  Compute C into CC_DST and O into CC_SRC2.  Note that

           since we've computed the flags into CC_SRC, these variables are

           currently dead.  */

        if (is_right) {

            tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);

            tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);

        } else {

            tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);

            tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);

        }

        tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);

        tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);

        set_cc_op(s, CC_OP_ADCOX);

    }

}


void do_savevm(const char *name)

{

    BlockDriverState *bs, *bs1;

    QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;

    int must_delete, ret, i;

    BlockDriverInfo bdi1, *bdi = &bdi1;

    QEMUFile *f;

    int saved_vm_running;

#ifdef _WIN32

    struct _timeb tb;

#else

    struct timeval tv;

#endif

    bs = get_bs_snapshots();

    if (!bs) {

        term_printf("No block device can accept snapshots\n");

        return;

    }

    /* ??? Should this occur after vm_stop?  */

    qemu_aio_flush();

    saved_vm_running = vm_running;

    vm_stop(0);

    must_delete = 0;

    if (name) {

        ret = bdrv_snapshot_find(bs, old_sn, name);

        if (ret >= 0) {

            must_delete = 1;

        }

    }

    memset(sn, 0, sizeof(*sn));

    if (must_delete) {

        pstrcpy(sn->name, sizeof(sn->name), old_sn->name);

        pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);

    } else {

        if (name)

            pstrcpy(sn->name, sizeof(sn->name), name);

    }

    /* fill auxiliary fields */

#ifdef _WIN32

    _ftime(&tb);

    sn->date_sec = tb.time;

    sn->date_nsec = tb.millitm * 1000000;

#else

    gettimeofday(&tv, NULL);

    sn->date_sec = tv.tv_sec;

    sn->date_nsec = tv.tv_usec * 1000;

#endif

    sn->vm_clock_nsec = qemu_get_clock(vm_clock);

    if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {

        term_printf("Device %s does not support VM state snapshots\n",

                    bdrv_get_device_name(bs));

        goto the_end;

    }

    /* save the VM state */

    f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);

    if (!f) {

        term_printf("Could not open VM state file\n");

        goto the_end;

    }

    ret = qemu_savevm_state(f);

    sn->vm_state_size = qemu_ftell(f);

    qemu_fclose(f);

    if (ret < 0) {

        term_printf("Error %d while writing VM\n", ret);

        goto the_end;

    }

    /* create the snapshots */

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

        bs1 = drives_table[i].bdrv;

        if (bdrv_has_snapshot(bs1)) {

            if (must_delete) {

                ret = bdrv_snapshot_delete(bs1, old_sn->id_str);

                if (ret < 0) {

                    term_printf("Error while deleting snapshot on '%s'\n",

                                bdrv_get_device_name(bs1));

                }

            }

            ret = bdrv_snapshot_create(bs1, sn);

            if (ret < 0) {

                term_printf("Error while creating snapshot on '%s'\n",

                            bdrv_get_device_name(bs1));

            }

        }

    }

 the_end:

    if (saved_vm_running)

        vm_start();

}


static void co_sleep_cb(void *opaque)

{

    CoSleepCB *sleep_cb = opaque;

    aio_co_wake(sleep_cb->co);

}


static int stellaris_enet_init(SysBusDevice *sbd)

{

    DeviceState *dev = DEVICE(sbd);

    stellaris_enet_state *s = STELLARIS_ENET(dev);

    memory_region_init_io(&s->mmio, OBJECT(s), &stellaris_enet_ops, s,

                          "stellaris_enet", 0x1000);

    sysbus_init_mmio(sbd, &s->mmio);

    sysbus_init_irq(sbd, &s->irq);

    qemu_macaddr_default_if_unset(&s->conf.macaddr);

    s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf,

                          object_get_typename(OBJECT(dev)), dev->id, s);

    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);

    stellaris_enet_reset(s);

    register_savevm(dev, "stellaris_enet", -1, 1,

                    stellaris_enet_save, stellaris_enet_load, s);

    return 0;

}


static int tcp_chr_new_client(CharDriverState *chr, QIOChannelSocket *sioc)

{

    TCPCharDriver *s = chr->opaque;

    if (s->ioc != NULL) {

	return -1;

    }

    s->ioc = QIO_CHANNEL(sioc);

    object_ref(OBJECT(sioc));

    if (s->do_nodelay) {

        qio_channel_set_delay(s->ioc, false);

    }

    if (s->listen_tag) {

        g_source_remove(s->listen_tag);

        s->listen_tag = 0;

    }

    if (s->do_telnetopt) {

        tcp_chr_telnet_init(chr);

    } else {

        tcp_chr_connect(chr);

    }

    return 0;

}


static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)

{

    int ret, size, bps;

    //    AVStream *st = s->streams[0];

    size= RAW_SAMPLES*s->streams[0]->codec->block_align;

    ret= av_get_packet(s->pb, pkt, size);

    pkt->stream_index = 0;

    if (ret < 0)

        return ret;

    bps= av_get_bits_per_sample(s->streams[0]->codec->codec_id);

    assert(bps); // if false there IS a bug elsewhere (NOT in this function)

    pkt->dts=

    pkt->pts= pkt->pos*8 / (bps * s->streams[0]->codec->channels);

    return ret;

}


static int vdpau_hevc_start_frame(AVCodecContext *avctx,

                                  const uint8_t *buffer, uint32_t size)

{

    HEVCContext *h = avctx->priv_data;

    HEVCFrame *pic = h->ref;

    struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;

    VdpPictureInfoHEVC *info = &pic_ctx->info.hevc;

    const HEVCSPS *sps = h->ps.sps;

    const HEVCPPS *pps = h->ps.pps;

    const SliceHeader *sh = &h->sh;

    const ScalingList *sl = pps->scaling_list_data_present_flag ?

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

    /* init VdpPictureInfoHEVC */

    /* SPS */

    info->chroma_format_idc = sps->chroma_format_idc;

    info->separate_colour_plane_flag = sps->separate_colour_plane_flag;

    info->pic_width_in_luma_samples = sps->width;

    info->pic_height_in_luma_samples = sps->height;

    info->bit_depth_luma_minus8 = sps->bit_depth - 8;

    info->bit_depth_chroma_minus8 = sps->bit_depth - 8;

    info->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4;

    /* Provide the value corresponding to the nuh_temporal_id of the frame

       to be decoded. */

    info->sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1;

    info->log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3;

    info->log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size;

    info->log2_min_transform_block_size_minus2 = sps->log2_min_tb_size - 2;

    info->log2_diff_max_min_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size;

    info->max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter;

    info->max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra;

    info->scaling_list_enabled_flag = sps->scaling_list_enable_flag;

    /* Scaling lists, in diagonal order, to be used for this frame. */

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

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

            /* Scaling List for 4x4 quantization matrix,

               indexed as ScalingList4x4[matrixId][i]. */

            uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j];

            info->ScalingList4x4[i][j] = sl->sl[0][i][pos];

        }

        for (size_t j = 0; j < 64; j++) {

            uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];

            /* Scaling List for 8x8 quantization matrix,

               indexed as ScalingList8x8[matrixId][i]. */

            info->ScalingList8x8[i][j] = sl->sl[1][i][pos];

            /* Scaling List for 16x16 quantization matrix,

               indexed as ScalingList16x16[matrixId][i]. */

            info->ScalingList16x16[i][j] = sl->sl[2][i][pos];

            if (i < 2) {

                /* Scaling List for 32x32 quantization matrix,

                   indexed as ScalingList32x32[matrixId][i]. */

                info->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos];

            }

        }

        /* Scaling List DC Coefficients for 16x16,

           indexed as ScalingListDCCoeff16x16[matrixId]. */

        info->ScalingListDCCoeff16x16[i] = sl->sl_dc[0][i];

        if (i < 2) {

            /* Scaling List DC Coefficients for 32x32,

               indexed as ScalingListDCCoeff32x32[matrixId]. */

            info->ScalingListDCCoeff32x32[i] = sl->sl_dc[1][i * 3];

        }

    }

    info->amp_enabled_flag = sps->amp_enabled_flag;

    info->sample_adaptive_offset_enabled_flag = sps->sao_enabled;

    info->pcm_enabled_flag = sps->pcm_enabled_flag;

    if (info->pcm_enabled_flag) {

        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */

        info->pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1;

        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */

        info->pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1;

        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */

        info->log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3;

        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */

        info->log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size;

        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */

        info->pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag;

    }

    /* Per spec, when zero, assume short_term_ref_pic_set_sps_flag

       is also zero. */

    info->num_short_term_ref_pic_sets = sps->nb_st_rps;

    info->long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag;

    /* Only needed if long_term_ref_pics_present_flag is set. Ignored

       otherwise. */

    info->num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps;

    info->sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag;

    info->strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag;

    /* Copy the HEVC Picture Parameter Set bitstream fields. */

    info->dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag;

    info->output_flag_present_flag = pps->output_flag_present_flag;

    info->num_extra_slice_header_bits = pps->num_extra_slice_header_bits;

    info->sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag;

    info->cabac_init_present_flag = pps->cabac_init_present_flag;

    info->num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1;

    info->num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1;

    info->init_qp_minus26 = pps->pic_init_qp_minus26;

    info->constrained_intra_pred_flag = pps->constrained_intra_pred_flag;

    info->transform_skip_enabled_flag = pps->transform_skip_enabled_flag;

    info->cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag;

    /* Only needed if cu_qp_delta_enabled_flag is set. Ignored otherwise. */

    info->diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth;

    info->pps_cb_qp_offset = pps->cb_qp_offset;

    info->pps_cr_qp_offset = pps->cr_qp_offset;

    info->pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag;

    info->weighted_pred_flag = pps->weighted_pred_flag;

    info->weighted_bipred_flag = pps->weighted_bipred_flag;

    info->transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag;

    info->tiles_enabled_flag = pps->tiles_enabled_flag;

    info->entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag;

    if (info->tiles_enabled_flag) {

        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */

        info->num_tile_columns_minus1 = pps->num_tile_columns - 1;

        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */

        info->num_tile_rows_minus1 = pps->num_tile_rows - 1;

        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */

        info->uniform_spacing_flag = pps->uniform_spacing_flag;

        /* Only need to set 0..num_tile_columns_minus1. The struct

           definition reserves up to the maximum of 20. Invalid values are

           ignored. */

        for (ssize_t i = 0; i < pps->num_tile_columns; i++) {

            info->column_width_minus1[i] = pps->column_width[i] - 1;

        }

        /* Only need to set 0..num_tile_rows_minus1. The struct

           definition reserves up to the maximum of 22. Invalid values are

           ignored.*/

        for (ssize_t i = 0; i < pps->num_tile_rows; i++) {

            info->row_height_minus1[i] = pps->row_height[i] - 1;

        }

        /* Only needed if tiles_enabled_flag is set. Invalid values are

           ignored. */

        info->loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag;

    }

    info->pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag;

    info->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag;

    /* Only valid if deblocking_filter_control_present_flag is set. Ignored

       otherwise. */

    info->deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag;

    /* Only valid if deblocking_filter_control_present_flag is set. Ignored

       otherwise. */

    info->pps_deblocking_filter_disabled_flag = pps->disable_dbf;

    /* Only valid if deblocking_filter_control_present_flag is set and

       pps_deblocking_filter_disabled_flag is not set. Ignored otherwise.*/

    info->pps_beta_offset_div2 = pps->beta_offset / 2;

    /* Only valid if deblocking_filter_control_present_flag is set and

       pps_deblocking_filter_disabled_flag is not set. Ignored otherwise. */

    info->pps_tc_offset_div2 = pps->tc_offset / 2;

    info->lists_modification_present_flag = pps->lists_modification_present_flag;

    info->log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2;

    info->slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag;

    /* Set to 1 if nal_unit_type is equal to IDR_W_RADL or IDR_N_LP.

       Set to zero otherwise. */

    info->IDRPicFlag = IS_IDR(h);

    /* Set to 1 if nal_unit_type in the range of BLA_W_LP to

       RSV_IRAP_VCL23, inclusive. Set to zero otherwise.*/

    info->RAPPicFlag = IS_IRAP(h);

    /* See section 7.4.7.1 of the specification. */

    info->CurrRpsIdx = sps->nb_st_rps;

    if (sh->short_term_ref_pic_set_sps_flag == 1) {

        for (size_t i = 0; i < sps->nb_st_rps; i++) {

            if (sh->short_term_rps == &sps->st_rps[i]) {

                info->CurrRpsIdx = i;

                break;

            }

        }

    }

    /* See section 7.4.7.2 of the specification. */

    info->NumPocTotalCurr = ff_hevc_frame_nb_refs(h);

    if (sh->short_term_ref_pic_set_sps_flag == 0 && sh->short_term_rps) {

        /* Corresponds to specification field, NumDeltaPocs[RefRpsIdx].

           Only applicable when short_term_ref_pic_set_sps_flag == 0.

           Implementations will ignore this value in other cases. See 7.4.8. */

        info->NumDeltaPocsOfRefRpsIdx = sh->short_term_rps->rps_idx_num_delta_pocs;

    }

    /* Section 7.6.3.1 of the H.265/HEVC Specification defines the syntax of

       the slice_segment_header. This header contains information that

       some VDPAU implementations may choose to skip. The VDPAU API

       requires client applications to track the number of bits used in the

       slice header for structures associated with short term and long term

       reference pictures. First, VDPAU requires the number of bits used by

       the short_term_ref_pic_set array in the slice_segment_header. */

    info->NumShortTermPictureSliceHeaderBits = sh->short_term_ref_pic_set_size;

    /* Second, VDPAU requires the number of bits used for long term reference

       pictures in the slice_segment_header. This is equal to the number

       of bits used for the contents of the block beginning with

       "if(long_term_ref_pics_present_flag)". */

    info->NumLongTermPictureSliceHeaderBits = sh->long_term_ref_pic_set_size;

    /* The value of PicOrderCntVal of the picture in the access unit

       containing the SEI message. The picture being decoded. */

    info->CurrPicOrderCntVal = h->poc;

    /* Slice Decoding Process - Reference Picture Sets */

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

        info->RefPics[i] = VDP_INVALID_HANDLE;

        info->PicOrderCntVal[i] = 0;

        info->IsLongTerm[i] = 0;

    }

    for (size_t i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {

        const HEVCFrame *frame = &h->DPB[i];

        if (frame != h->ref && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF |

                                                HEVC_FRAME_FLAG_SHORT_REF))) {

            if (j > 16) {

                av_log(avctx, AV_LOG_WARNING,

                     "VDPAU only supports up to 16 references in the DPB. "

                     "This frame may not be decoded correctly.\n");

                break;

            }

            /* Array of video reference surfaces.

               Set any unused positions to VDP_INVALID_HANDLE. */

            info->RefPics[j] = ff_vdpau_get_surface_id(frame->frame);

            /* Array of picture order counts. These correspond to positions

               in the RefPics array. */

            info->PicOrderCntVal[j] = frame->poc;

            /* Array used to specify whether a particular RefPic is

               a long term reference. A value of "1" indicates a long-term

               reference. */

            // XXX: Setting this caused glitches in the nvidia implementation

            // Always setting it to zero, produces correct results

            //info->IsLongTerm[j] = frame->flags & HEVC_FRAME_FLAG_LONG_REF;

            info->IsLongTerm[j] = 0;

            j++;

        }

    }

    /* Copy of specification field, see Section 8.3.2 of the

       H.265/HEVC Specification. */

    info->NumPocStCurrBefore = h->rps[ST_CURR_BEF].nb_refs;

    if (info->NumPocStCurrBefore > 8) {

        av_log(avctx, AV_LOG_WARNING,

             "VDPAU only supports up to 8 references in StCurrBefore. "

             "This frame may not be decoded correctly.\n");

        info->NumPocStCurrBefore = 8;

    }

    /* Copy of specification field, see Section 8.3.2 of the

       H.265/HEVC Specification. */

    info->NumPocStCurrAfter = h->rps[ST_CURR_AFT].nb_refs;

    if (info->NumPocStCurrAfter > 8) {

        av_log(avctx, AV_LOG_WARNING,

             "VDPAU only supports up to 8 references in StCurrAfter. "

             "This frame may not be decoded correctly.\n");

        info->NumPocStCurrAfter = 8;

    }

    /* Copy of specification field, see Section 8.3.2 of the

       H.265/HEVC Specification. */

    info->NumPocLtCurr = h->rps[LT_CURR].nb_refs;

    if (info->NumPocLtCurr > 8) {

        av_log(avctx, AV_LOG_WARNING,

             "VDPAU only supports up to 8 references in LtCurr. "

             "This frame may not be decoded correctly.\n");

        info->NumPocLtCurr = 8;

    }

    /* Reference Picture Set list, one of the short-term RPS. These

       correspond to positions in the RefPics array. */

    for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {

        HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i];

        if (frame) {

            uint8_t found = 0;

            uintptr_t id = ff_vdpau_get_surface_id(frame->frame);

            for (size_t k = 0; k < 16; k++) {

                if (id == info->RefPics[k]) {

                    info->RefPicSetStCurrBefore[j] = k;

                    j++;

                    found = 1;

                    break;

                }

            }

            if (!found) {

                av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n",

                       (void *)id);

            }

        } else {

            av_log(avctx, AV_LOG_WARNING, "missing STR Before frame: %zd\n", i);

        }

    }

    /* Reference Picture Set list, one of the short-term RPS. These

       correspond to positions in the RefPics array. */

    for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {

        HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i];

        if (frame) {

            uint8_t found = 0;

            uintptr_t id = ff_vdpau_get_surface_id(frame->frame);

            for (size_t k = 0; k < 16; k++) {

                if (id == info->RefPics[k]) {

                    info->RefPicSetStCurrAfter[j] = k;

                    j++;

                    found = 1;

                    break;

                }

            }

            if (!found) {

                av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n",

                       (void *)id);

            }

        } else {

            av_log(avctx, AV_LOG_WARNING, "missing STR After frame: %zd\n", i);

        }

    }

    /* Reference Picture Set list, one of the long-term RPS. These

       correspond to positions in the RefPics array. */

    for (ssize_t i = 0, j = 0; i < h->rps[LT_CURR].nb_refs; i++) {

        HEVCFrame *frame = h->rps[LT_CURR].ref[i];

        if (frame) {

            uint8_t found = 0;

            uintptr_t id = ff_vdpau_get_surface_id(frame->frame);

            for (size_t k = 0; k < 16; k++) {

                if (id == info->RefPics[k]) {

                    info->RefPicSetLtCurr[j] = k;

                    j++;

                    found = 1;

                    break;

                }

            }

            if (!found) {

                av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n",

                       (void *)id);

            }

        } else {

            av_log(avctx, AV_LOG_WARNING, "missing LTR frame: %zd\n", i);

        }

    }

    return ff_vdpau_common_start_frame(pic_ctx, buffer, size);

}


void usb_cancel_packet(USBPacket * p)

{

    assert(p->owner != NULL);

    usb_device_cancel_packet(p->owner->dev, p);

    p->owner = NULL;

}


static int cmp_func_names(const char *a, const char *b)

{

    int ascii_diff, digit_diff;

    for (; !(ascii_diff = *a - *b) && *a; a++, b++);

    for (; av_isdigit(*a) && av_isdigit(*b); a++, b++);

    return (digit_diff = av_isdigit(*a) - av_isdigit(*b)) ? digit_diff : ascii_diff;

}


vu_queue_fill(VuDev *dev, VuVirtq *vq,

              const VuVirtqElement *elem,

              unsigned int len, unsigned int idx)

{

    struct vring_used_elem uelem;

    if (unlikely(dev->broken)) {

        return;

    }

    vu_log_queue_fill(dev, vq, elem, len);

    idx = (idx + vq->used_idx) % vq->vring.num;

    uelem.id = elem->index;

    uelem.len = len;

    vring_used_write(dev, vq, &uelem, idx);

}


void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr)

{

    KVMState *s = kvm_state;

    KVMDirtyLog d;

    KVMSlot *mem = kvm_lookup_slot(s, start_addr);

    unsigned long alloc_size;

    ram_addr_t addr;

    target_phys_addr_t phys_addr = start_addr;

    dprintf("sync addr: %llx into %lx\n", start_addr, mem->phys_offset);

    if (mem == NULL) {

            fprintf(stderr, "BUG: %s: invalid parameters\n", __func__);

            return;

    }

    alloc_size = mem->memory_size >> TARGET_PAGE_BITS / sizeof(d.dirty_bitmap);

    d.dirty_bitmap = qemu_mallocz(alloc_size);

    d.slot = mem->slot;

    dprintf("slot %d, phys_addr %llx, uaddr: %llx\n",

            d.slot, mem->start_addr, mem->phys_offset);

    if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {

        dprintf("ioctl failed %d\n", errno);

        goto out;

    }

    phys_addr = start_addr;

    for (addr = mem->phys_offset; phys_addr < end_addr; phys_addr+= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {

        unsigned long *bitmap = (unsigned long *)d.dirty_bitmap;

        unsigned nr = (phys_addr - start_addr) >> TARGET_PAGE_BITS;

        unsigned word = nr / (sizeof(*bitmap) * 8);

        unsigned bit = nr % (sizeof(*bitmap) * 8);

        if ((bitmap[word] >> bit) & 1)

            cpu_physical_memory_set_dirty(addr);

    }

out:

    qemu_free(d.dirty_bitmap);

}


static void gen_mullwo(DisasContext *ctx)

{

    TCGv_i32 t0 = tcg_temp_new_i32();

    TCGv_i32 t1 = tcg_temp_new_i32();

    tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]);

    tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]);

    tcg_gen_muls2_i32(t0, t1, t0, t1);

#if defined(TARGET_PPC64)

    tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1);

#else

    tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], t0);

#endif

    tcg_gen_sari_i32(t0, t0, 31);

    tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t1);

    tcg_gen_extu_i32_tl(cpu_ov, t0);

    tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);

    tcg_temp_free_i32(t0);

    tcg_temp_free_i32(t1);

    if (unlikely(Rc(ctx->opcode) != 0))

        gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);


static int http_parse_request(HTTPContext *c)

{

    char *p;

    int post;

    char cmd[32];

    char info[1024], *filename;

    char url[1024], *q;

    char protocol[32];

    char msg[1024];

    const char *mime_type;

    FFStream *stream;

    p = c->buffer;

    q = cmd;

    while (!isspace(*p) && *p != '\0') {

        if ((q - cmd) < sizeof(cmd) - 1)

            *q++ = *p;

        p++;

    }

    *q = '\0';

    if (!strcmp(cmd, "GET"))

        post = 0;

    else if (!strcmp(cmd, "POST"))

        post = 1;

    else

        return -1;

    while (isspace(*p)) p++;

    q = url;

    while (!isspace(*p) && *p != '\0') {

        if ((q - url) < sizeof(url) - 1)

            *q++ = *p;

        p++;

    }

    *q = '\0';

    while (isspace(*p)) p++;

    q = protocol;

    while (!isspace(*p) && *p != '\0') {

        if ((q - protocol) < sizeof(protocol) - 1)

            *q++ = *p;

        p++;

    }

    *q = '\0';

    if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))

        return -1;

    /* find the filename and the optional info string in the request */

    p = url;

    if (*p == '/')

        p++;

    filename = p;

    p = strchr(p, '?');

    if (p) {

        strcpy(info, p);

        *p = '\0';

    } else {

        info[0] = '\0';

    }

    stream = first_stream;

    while (stream != NULL) {

        if (!strcmp(stream->filename, filename))

            break;

        stream = stream->next;

    }

    if (stream == NULL) {

        sprintf(msg, "File '%s' not found", url);

        goto send_error;

    }

    c->stream = stream;

    /* should do it after so that the size can be computed */

    {

        char buf1[32], buf2[32], *p;

        time_t ti;

        /* XXX: reentrant function ? */

        p = inet_ntoa(c->from_addr.sin_addr);

        strcpy(buf1, p);

        ti = time(NULL);

        p = ctime(&ti);

        strcpy(buf2, p);

        p = buf2 + strlen(p) - 1;

        if (*p == '\n')

            *p = '\0';

        http_log("%s - - [%s] \"%s %s %s\" %d %d\n",

                 buf1, buf2, cmd, url, protocol, 200, 1024);

    }

    /* XXX: add there authenticate and IP match */

    if (post) {

        /* if post, it means a feed is being sent */

        if (!stream->is_feed) {

            sprintf(msg, "POST command not handled");

            goto send_error;

        }

        if (http_start_receive_data(c) < 0) {

            sprintf(msg, "could not open feed");

            goto send_error;

        }

        c->http_error = 0;

        c->state = HTTPSTATE_RECEIVE_DATA;

        return 0;

    }

    if (c->stream->stream_type == STREAM_TYPE_STATUS)

        goto send_stats;

    /* open input stream */

    if (open_input_stream(c, info) < 0) {

        sprintf(msg, "Input stream corresponding to '%s' not found", url);

        goto send_error;

    }

    /* prepare http header */

    q = c->buffer;

    q += sprintf(q, "HTTP/1.0 200 OK\r\n");

    mime_type = c->stream->fmt->mime_type;

    if (!mime_type)

        mime_type = "application/x-octet_stream";

    q += sprintf(q, "Pragma: no-cache\r\n");

    /* for asf, we need extra headers */

    if (!strcmp(c->stream->fmt->name,"asf")) {

        q += sprintf(q, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=1234\r\nPragma: features=\"broadcast\"\r\n");

        mime_type = "application/octet-stream";

    }

    q += sprintf(q, "Content-Type: %s\r\n", mime_type);

    q += sprintf(q, "\r\n");

    /* prepare output buffer */

    c->http_error = 0;

    c->buffer_ptr = c->buffer;

    c->buffer_end = q;

    c->state = HTTPSTATE_SEND_HEADER;

    return 0;

 send_error:

    c->http_error = 404;

    q = c->buffer;

    q += sprintf(q, "HTTP/1.0 404 Not Found\r\n");

    q += sprintf(q, "Content-type: %s\r\n", "text/html");

    q += sprintf(q, "\r\n");

    q += sprintf(q, "\n");

    q += sprintf(q, "<TITLE>404 Not Found</TITLE>\n");

    q += sprintf(q, "%s\n", msg);

    q += sprintf(q, "\n");

    /* prepare output buffer */

    c->buffer_ptr = c->buffer;

    c->buffer_end = q;

    c->state = HTTPSTATE_SEND_HEADER;

    return 0;

 send_stats:

    compute_stats(c);

    c->http_error = 200; /* horrible : we use this value to avoid

                            going to the send data state */

    c->state = HTTPSTATE_SEND_HEADER;

    return 0;

}


static int add_doubles_metadata(int count,

                                const char *name, const char *sep,

                                TiffContext *s)

{

    char *ap;

    int i;

    double *dp;

    if (count >= INT_MAX / sizeof(int64_t) || count <= 0)

        return AVERROR_INVALIDDATA;

    if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t))

        return AVERROR_INVALIDDATA;

    dp = av_malloc(count * sizeof(double));

    if (!dp)

        return AVERROR(ENOMEM);

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

        dp[i] = tget_double(&s->gb, s->le);

    ap = doubles2str(dp, count, sep);

    av_freep(&dp);

    if (!ap)

        return AVERROR(ENOMEM);

    av_dict_set(avpriv_frame_get_metadatap(&s->picture), name, ap, AV_DICT_DONT_STRDUP_VAL);

    return 0;

}


static av_cold int che_configure(AACContext *ac,

                                 enum ChannelPosition che_pos,

                                 int type, int id, int *channels)

{

    if (*channels >= MAX_CHANNELS)

        return AVERROR_INVALIDDATA;

    if (che_pos) {

        if (!ac->che[type][id]) {

            if (!(ac->che[type][id] = av_mallocz(sizeof(ChannelElement))))

                return AVERROR(ENOMEM);

            ff_aac_sbr_ctx_init(ac, &ac->che[type][id]->sbr);

        }

        if (type != TYPE_CCE) {

            ac->output_element[(*channels)++] = &ac->che[type][id]->ch[0];

            if (type == TYPE_CPE ||

                (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) {

                ac->output_element[(*channels)++] = &ac->che[type][id]->ch[1];

            }

        }

    } else {

        if (ac->che[type][id])

            ff_aac_sbr_ctx_close(&ac->che[type][id]->sbr);

        av_freep(&ac->che[type][id]);

    }

    return 0;

}


int64_t qdict_get_int(const QDict *qdict, const char *key)

{

    QObject *obj = qdict_get_obj(qdict, key, QTYPE_QINT);

    return qint_get_int(qobject_to_qint(obj));

}


static target_ulong h_client_architecture_support(PowerPCCPU *cpu,

                                                  sPAPRMachineState *spapr,

                                                  target_ulong opcode,

                                                  target_ulong *args)

{

    target_ulong list = ppc64_phys_to_real(args[0]);

    target_ulong ov_table;

    bool explicit_match = false; /* Matched the CPU's real PVR */

    uint32_t max_compat = cpu->max_compat;

    uint32_t best_compat = 0;

    int i;

    sPAPROptionVector *ov5_guest, *ov5_cas_old, *ov5_updates;

    bool guest_radix;

    /*

     * We scan the supplied table of PVRs looking for two things

     *   1. Is our real CPU PVR in the list?

     *   2. What's the "best" listed logical PVR

     */

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

        uint32_t pvr, pvr_mask;

        pvr_mask = ldl_be_phys(&address_space_memory, list);

        pvr = ldl_be_phys(&address_space_memory, list + 4);

        list += 8;

        if (~pvr_mask & pvr) {

            break; /* Terminator record */

        }

        if ((cpu->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask)) {

            explicit_match = true;

        } else {

            if (ppc_check_compat(cpu, pvr, best_compat, max_compat)) {

                best_compat = pvr;

            }

        }

    }

    if ((best_compat == 0) && (!explicit_match || max_compat)) {

        /* We couldn't find a suitable compatibility mode, and either

         * the guest doesn't support "raw" mode for this CPU, or raw

         * mode is disabled because a maximum compat mode is set */

        return H_HARDWARE;

    }

    /* Parsing finished */

    trace_spapr_cas_pvr(cpu->compat_pvr, explicit_match, best_compat);

    /* Update CPUs */

    if (cpu->compat_pvr != best_compat) {

        Error *local_err = NULL;

        ppc_set_compat_all(best_compat, &local_err);

        if (local_err) {

            error_report_err(local_err);

            return H_HARDWARE;

        }

    }

    /* For the future use: here @ov_table points to the first option vector */

    ov_table = list;

    ov5_guest = spapr_ovec_parse_vector(ov_table, 5);

    if (spapr_ovec_test(ov5_guest, OV5_MMU_BOTH)) {

        error_report("guest requested hash and radix MMU, which is invalid.");

        exit(EXIT_FAILURE);

    }

    /* The radix/hash bit in byte 24 requires special handling: */

    guest_radix = spapr_ovec_test(ov5_guest, OV5_MMU_RADIX_300);

    spapr_ovec_clear(ov5_guest, OV5_MMU_RADIX_300);

    /* NOTE: there are actually a number of ov5 bits where input from the

     * guest is always zero, and the platform/QEMU enables them independently

     * of guest input. To model these properly we'd want some sort of mask,

     * but since they only currently apply to memory migration as defined

     * by LoPAPR 1.1, 14.5.4.8, which QEMU doesn't implement, we don't need

     * to worry about this for now.

     */

    ov5_cas_old = spapr_ovec_clone(spapr->ov5_cas);

    /* full range of negotiated ov5 capabilities */

    spapr_ovec_intersect(spapr->ov5_cas, spapr->ov5, ov5_guest);

    spapr_ovec_cleanup(ov5_guest);

    /* capabilities that have been added since CAS-generated guest reset.

     * if capabilities have since been removed, generate another reset

     */

    ov5_updates = spapr_ovec_new();

    spapr->cas_reboot = spapr_ovec_diff(ov5_updates,

                                        ov5_cas_old, spapr->ov5_cas);

    /* Now that processing is finished, set the radix/hash bit for the

     * guest if it requested a valid mode; otherwise terminate the boot. */

    if (guest_radix) {

        if (kvm_enabled() && !kvmppc_has_cap_mmu_radix()) {

            error_report("Guest requested unavailable MMU mode (radix).");

            exit(EXIT_FAILURE);

        }

        spapr_ovec_set(spapr->ov5_cas, OV5_MMU_RADIX_300);

    } else {

        if (kvm_enabled() && kvmppc_has_cap_mmu_radix()

            && !kvmppc_has_cap_mmu_hash_v3()) {

            error_report("Guest requested unavailable MMU mode (hash).");

            exit(EXIT_FAILURE);

        }

    }

    if (!spapr->cas_reboot) {

        spapr->cas_reboot =

            (spapr_h_cas_compose_response(spapr, args[1], args[2],

                                          ov5_updates) != 0);

    }

    spapr_ovec_cleanup(ov5_updates);

    if (spapr->cas_reboot) {

        qemu_system_reset_request();

    } else {

        /* If ppc_spapr_reset() did not set up a HPT but one is necessary

         * (because the guest isn't going to use radix) then set it up here. */

        if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) {

            /* legacy hash or new hash: */

            spapr_setup_hpt_and_vrma(spapr);

        }

    }

    return H_SUCCESS;

}


static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, BitstreamContext *bc,

                              const char *name, uint32_t *write_to,

                              uint32_t range_min, uint32_t range_max)

{

    uint32_t value;

    int position;

    if (ctx->trace_enable) {

        char bits[65];

        unsigned int k;

        int i, j;

        position = bitstream_tell(bc);

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

            k = bitstream_read_bit(bc);

            bits[i] = k ? '1' : '0';

            if (k)

                break;

        }

        if (i >= 32) {

            av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb "

                   "code found while reading %s: "

                   "more than 31 zeroes.\n", name);

            return AVERROR_INVALIDDATA;

        }

        value = 1;

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

            k = bitstream_read_bit(bc);

            bits[i + j + 1] = k ? '1' : '0';

            value = value << 1 | k;

        }

        bits[i + j + 1] = 0;

        --value;

        ff_cbs_trace_syntax_element(ctx, position, name, bits, value);

    } else {

        value = get_ue_golomb_long(bc);

    }

    if (value < range_min || value > range_max) {

        av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "

               "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",

               name, value, range_min, range_max);

        return AVERROR_INVALIDDATA;

    }

    *write_to = value;

    return 0;

}


void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
                               int64_t bps_wr,
                               int64_t iops,
                               int64_t iops_rd,
                               int64_t iops_wr,
                               bool has_bps_max,
                               int64_t bps_max,
                               bool has_bps_rd_max,
                               int64_t bps_rd_max,
                               bool has_bps_wr_max,
                               int64_t bps_wr_max,
                               bool has_iops_max,
                               int64_t iops_max,
                               bool has_iops_rd_max,
                               int64_t iops_rd_max,
                               bool has_iops_wr_max,
                               int64_t iops_wr_max,
                               bool has_iops_size,
                               int64_t iops_size, Error **errp)
{
    ThrottleConfig cfg;
    BlockDriverState *bs;
    AioContext *aio_context;
    bs = bdrv_find(device);
    if (!bs) {
        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
        return;
    }
    memset(&cfg, 0, sizeof(cfg));
    cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
    cfg.buckets[THROTTLE_BPS_READ].avg  = bps_rd;
    cfg.buckets[THROTTLE_BPS_WRITE].avg = bps_wr;
    cfg.buckets[THROTTLE_OPS_TOTAL].avg = iops;
    cfg.buckets[THROTTLE_OPS_READ].avg  = iops_rd;
    cfg.buckets[THROTTLE_OPS_WRITE].avg = iops_wr;
    if (has_bps_max) {
        cfg.buckets[THROTTLE_BPS_TOTAL].max = bps_max;
    }
    if (has_bps_rd_max) {
        cfg.buckets[THROTTLE_BPS_READ].max = bps_rd_max;
    }
    if (has_bps_wr_max) {
        cfg.buckets[THROTTLE_BPS_WRITE].max = bps_wr_max;
    }
    if (has_iops_max) {
        cfg.buckets[THROTTLE_OPS_TOTAL].max = iops_max;
    }
    if (has_iops_rd_max) {
        cfg.buckets[THROTTLE_OPS_READ].max = iops_rd_max;
    }
    if (has_iops_wr_max) {
        cfg.buckets[THROTTLE_OPS_WRITE].max = iops_wr_max;
    }
    if (has_iops_size) {
        cfg.op_size = iops_size;
    }
    if (!check_throttle_config(&cfg, errp)) {
        return;
    }
    aio_context = bdrv_get_aio_context(bs);
    aio_context_acquire(aio_context);
    if (!bs->io_limits_enabled && throttle_enabled(&cfg)) {
        bdrv_io_limits_enable(bs);
    } else if (bs->io_limits_enabled && !throttle_enabled(&cfg)) {
        bdrv_io_limits_disable(bs);
    }
    if (bs->io_limits_enabled) {
        bdrv_set_io_limits(bs, &cfg);
    }
}


void palette8torgb32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette)

{

	long i;

/*

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

		((unsigned *)dst)[i] = ((unsigned *)palette)[ src[i] ];

*/

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

	{

		#ifdef WORDS_BIGENDIAN

			dst[3]= palette[ src[i]*4+2 ];

			dst[2]= palette[ src[i]*4+1 ];

			dst[1]= palette[ src[i]*4+0 ];

		#else

		//FIXME slow?

			dst[0]= palette[ src[i]*4+2 ];

			dst[1]= palette[ src[i]*4+1 ];

			dst[2]= palette[ src[i]*4+0 ];

			//dst[3]= 0; /* do we need this cleansing? */

		#endif

		dst+= 4;

	}

}


const char * avdevice_configuration(void)

{

    return FFMPEG_CONFIGURATION;

}


int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end)

{

    const uint8_t *base = data;

    if (data >= data_end)

        return -1;

    switch (*data++) {

    case AMF_DATA_TYPE_NUMBER:      return 9;

    case AMF_DATA_TYPE_BOOL:        return 2;

    case AMF_DATA_TYPE_STRING:      return 3 + AV_RB16(data);

    case AMF_DATA_TYPE_LONG_STRING: return 5 + AV_RB32(data);

    case AMF_DATA_TYPE_NULL:        return 1;

    case AMF_DATA_TYPE_ARRAY:

        data += 4;

    case AMF_DATA_TYPE_OBJECT:

        for (;;) {

            int size = bytestream_get_be16(&data);

            int t;

            if (!size) {

                data++;

                break;

            }

            if (data + size >= data_end || data + size < data)

                return -1;

            data += size;

            t = ff_amf_tag_size(data, data_end);

            if (t < 0 || data + t >= data_end)

                return -1;

            data += t;

        }

        return data - base;

    case AMF_DATA_TYPE_OBJECT_END:  return 1;

    default:                        return -1;

    }

}


static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)

{

    struct video_data *s = s1->priv_data;

    AVStream *st;

    int width, height;

    int res, frame_rate, frame_rate_base;

    uint32_t desired_format, capabilities;

    if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {

        av_log(s1, AV_LOG_ERROR, "Missing/Wrong width, height or framerate\n");

        return -1;

    }

    width = ap->width;

    height = ap->height;

    frame_rate = ap->time_base.den;

    frame_rate_base = ap->time_base.num;

    if((unsigned)width > 32767 || (unsigned)height > 32767) {

        av_log(s1, AV_LOG_ERROR, "Wrong size %dx%d\n", width, height);

        return -1;

    }

    st = av_new_stream(s1, 0);

    if (!st) {

        return AVERROR(ENOMEM);

    }

    av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */

    s->width = width;

    s->height = height;

    s->frame_rate      = frame_rate;

    s->frame_rate_base = frame_rate_base;

    capabilities = 0;

    s->fd = device_open(s1, &capabilities);

    if (s->fd < 0) {

        av_free(st);

        return AVERROR(EIO);

    }

    av_log(s1, AV_LOG_INFO, "[%d]Capabilities: %x\n", s->fd, capabilities);

    desired_format = fmt_ff2v4l(ap->pix_fmt);

    if (desired_format == 0 || (device_init(s1, &width, &height, desired_format) < 0)) {

        int i, done;

        done = 0; i = 0;

        while (!done) {

            desired_format = fmt_conversion_table[i].v4l2_fmt;

            if (device_init(s1, &width, &height, desired_format) < 0) {

                desired_format = 0;

                i++;

            } else {

               done = 1;

            }

            if (i == sizeof(fmt_conversion_table) / sizeof(struct fmt_map)) {

               done = 1;

            }

        }

    }

    if (desired_format == 0) {

        av_log(s1, AV_LOG_ERROR, "Cannot find a proper format.\n");

        close(s->fd);

        av_free(st);

        return AVERROR(EIO);

    }

    s->frame_format = desired_format;

    if( v4l2_set_parameters( s1, ap ) < 0 )

        return AVERROR(EIO);

    st->codec->pix_fmt = fmt_v4l2ff(desired_format);

    s->frame_size = avpicture_get_size(st->codec->pix_fmt, width, height);

    if (capabilities & V4L2_CAP_STREAMING) {

        s->io_method = io_mmap;

        res = mmap_init(s1);

        if (res == 0) {

            res = mmap_start(s1);

        }

    } else {

        s->io_method = io_read;

        res = read_init(s1);

    }

    if (res < 0) {

        close(s->fd);

        av_free(st);

        return AVERROR(EIO);

    }

    s->top_field_first = first_field(s->fd);

    st->codec->codec_type = CODEC_TYPE_VIDEO;

    st->codec->codec_id = CODEC_ID_RAWVIDEO;

    st->codec->width = width;

    st->codec->height = height;

    st->codec->time_base.den = frame_rate;

    st->codec->time_base.num = frame_rate_base;

    st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;

    return 0;

}


const char *bdrv_get_node_name(const BlockDriverState *bs)

{

    return bs->node_name;

}


static unsigned decode_skip_count(GetBitContext* gb)

{

    unsigned value;

    // This function reads a maximum of 23 bits,

    // which is within the padding space

    if (!can_safely_read(gb, 1))

        return -1;

    value = get_bits1(gb);

    if (!value)

        return value;

    value += get_bits(gb, 3);

    if (value != (1 + ((1 << 3) - 1)))

        return value;

    value += get_bits(gb, 7);

    if (value != (1 + ((1 << 3) - 1)) + ((1 << 7) - 1))

        return value;

    return value + get_bits(gb, 12);

}


void qmp_drive_mirror(const char *device, const char *target,

                      bool has_format, const char *format,

                      bool has_node_name, const char *node_name,

                      bool has_replaces, const char *replaces,

                      enum MirrorSyncMode sync,

                      bool has_mode, enum NewImageMode mode,

                      bool has_speed, int64_t speed,

                      bool has_granularity, uint32_t granularity,

                      bool has_buf_size, int64_t buf_size,

                      bool has_on_source_error, BlockdevOnError on_source_error,

                      bool has_on_target_error, BlockdevOnError on_target_error,

                      bool has_unmap, bool unmap,

                      Error **errp)

{

    BlockBackend *blk;

    BlockDriverState *bs;

    BlockDriverState *source, *target_bs;

    AioContext *aio_context;

    BlockDriver *drv = NULL;

    Error *local_err = NULL;

    QDict *options = NULL;

    int flags;

    int64_t size;

    int ret;

    if (!has_speed) {

        speed = 0;

    }

    if (!has_on_source_error) {

        on_source_error = BLOCKDEV_ON_ERROR_REPORT;

    }

    if (!has_on_target_error) {

        on_target_error = BLOCKDEV_ON_ERROR_REPORT;

    }

    if (!has_mode) {

        mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;

    }

    if (!has_granularity) {

        granularity = 0;

    }

    if (!has_buf_size) {

        buf_size = 0;

    }

    if (!has_unmap) {

        unmap = true;

    }

    if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) {

        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",

                   "a value in range [512B, 64MB]");

        return;

    }

    if (granularity & (granularity - 1)) {

        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",

                   "power of 2");

        return;

    }

    blk = blk_by_name(device);

    if (!blk) {

        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,

                  "Device '%s' not found", device);

        return;

    }

    bs = blk_bs(blk);

    aio_context = bdrv_get_aio_context(bs);

    aio_context_acquire(aio_context);

    if (!bdrv_is_inserted(bs)) {

        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);

        goto out;

    }

    if (!has_format) {

        format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;

    }

    if (format) {

        drv = bdrv_find_format(format);

        if (!drv) {

            error_setg(errp, QERR_INVALID_BLOCK_FORMAT, format);

            goto out;

        }

    }

    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR, errp)) {

        goto out;

    }

    flags = bs->open_flags | BDRV_O_RDWR;

    source = bs->backing_hd;

    if (!source && sync == MIRROR_SYNC_MODE_TOP) {

        sync = MIRROR_SYNC_MODE_FULL;

    }

    if (sync == MIRROR_SYNC_MODE_NONE) {

        source = bs;

    }

    size = bdrv_getlength(bs);

    if (size < 0) {

        error_setg_errno(errp, -size, "bdrv_getlength failed");

        goto out;

    }

    if (has_replaces) {

        BlockDriverState *to_replace_bs;

        AioContext *replace_aio_context;

        int64_t replace_size;

        if (!has_node_name) {

            error_setg(errp, "a node-name must be provided when replacing a"

                             " named node of the graph");

            goto out;

        }

        to_replace_bs = check_to_replace_node(replaces, &local_err);

        if (!to_replace_bs) {

            error_propagate(errp, local_err);

            goto out;

        }

        replace_aio_context = bdrv_get_aio_context(to_replace_bs);

        aio_context_acquire(replace_aio_context);

        replace_size = bdrv_getlength(to_replace_bs);

        aio_context_release(replace_aio_context);

        if (size != replace_size) {

            error_setg(errp, "cannot replace image with a mirror image of "

                             "different size");

            goto out;

        }

    }

    if ((sync == MIRROR_SYNC_MODE_FULL || !source)

        && mode != NEW_IMAGE_MODE_EXISTING)

    {

        /* create new image w/o backing file */

        assert(format && drv);

        bdrv_img_create(target, format,

                        NULL, NULL, NULL, size, flags, &local_err, false);

    } else {

        switch (mode) {

        case NEW_IMAGE_MODE_EXISTING:

            break;

        case NEW_IMAGE_MODE_ABSOLUTE_PATHS:

            /* create new image with backing file */

            bdrv_img_create(target, format,

                            source->filename,

                            source->drv->format_name,

                            NULL, size, flags, &local_err, false);

            break;

        default:

            abort();

        }

    }

    if (local_err) {

        error_propagate(errp, local_err);

        goto out;

    }

    if (has_node_name) {

        options = qdict_new();

        qdict_put(options, "node-name", qstring_from_str(node_name));

    }

    /* Mirroring takes care of copy-on-write using the source's backing

     * file.

     */

    target_bs = NULL;

    ret = bdrv_open(&target_bs, target, NULL, options,

                    flags | BDRV_O_NO_BACKING, drv, &local_err);

    if (ret < 0) {

        error_propagate(errp, local_err);

        goto out;

    }

    bdrv_set_aio_context(target_bs, aio_context);

    /* pass the node name to replace to mirror start since it's loose coupling

     * and will allow to check whether the node still exist at mirror completion

     */

    mirror_start(bs, target_bs,

                 has_replaces ? replaces : NULL,

                 speed, granularity, buf_size, sync,

                 on_source_error, on_target_error,

                 unmap,

                 block_job_cb, bs, &local_err);

    if (local_err != NULL) {

        bdrv_unref(target_bs);

        error_propagate(errp, local_err);

        goto out;

    }

out:

    aio_context_release(aio_context);

}


build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt)

{

    AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);

    bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,

                             true /* fseg memory */);

    memcpy(&rsdp->signature, "RSD PTR ", 8);

    memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);

    rsdp->rsdt_physical_address = cpu_to_le32(rsdt);

    /* Address to be filled by Guest linker */

    bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,

                                   ACPI_BUILD_TABLE_FILE,

                                   &rsdp->rsdt_physical_address,

                                   sizeof rsdp->rsdt_physical_address);

    rsdp->checksum = 0;

    /* Checksum to be filled by Guest linker */

    bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,

                                    rsdp, sizeof *rsdp,

                                    &rsdp->checksum);

    return rsdp_table;

}


static int tcp_chr_new_client(CharDriverState *chr, QIOChannelSocket *sioc)

{

    TCPCharDriver *s = chr->opaque;

    if (s->ioc != NULL) {

	return -1;

    }

    s->ioc = QIO_CHANNEL(sioc);

    object_ref(OBJECT(sioc));

    if (s->do_nodelay) {

        qio_channel_set_delay(s->ioc, false);

    }

    if (s->listen_tag) {

        g_source_remove(s->listen_tag);

        s->listen_tag = 0;

    }

    tcp_chr_connect(chr);

    return 0;

}


static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v,

                                          const char *name, void *opaque,

                                          Error **errp)

{

    PCIHostState *h = PCI_HOST_BRIDGE(obj);

    Range w64;

    pci_bus_get_w64_range(h->bus, &w64);

    visit_type_uint64(v, name, &w64.begin, errp);

}


static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)

{

    DMAState *s = opaque;

    uint32_t saddr;

    saddr = (addr & DMA_MASK) >> 2;

    DPRINTF("write dmareg " TARGET_FMT_plx ": 0x%8.8x -> 0x%8.8x\n", addr,

            s->dmaregs[saddr], val);

    switch (saddr) {

    case 0:

        if (val & DMA_INTREN) {

            if (val & DMA_INTR) {

                DPRINTF("Raise IRQ\n");

                qemu_irq_raise(s->irq);

            }

        } else {

            if (s->dmaregs[0] & (DMA_INTR | DMA_INTREN)) {

                DPRINTF("Lower IRQ\n");

                qemu_irq_lower(s->irq);

            }

        }

        if (val & DMA_RESET) {

            qemu_irq_raise(s->dev_reset);

            qemu_irq_lower(s->dev_reset);

        } else if (val & DMA_DRAIN_FIFO) {

            val &= ~DMA_DRAIN_FIFO;

        } else if (val == 0)

            val = DMA_DRAIN_FIFO;

        val &= 0x0fffffff;

        val |= DMA_VER;

        break;

    case 1:

        s->dmaregs[0] |= DMA_LOADED;

        break;

    default:

        break;

    }

    s->dmaregs[saddr] = val;

}


static uint64_t nvic_sysreg_read(void *opaque, target_phys_addr_t addr,

                                 unsigned size)

{

    /* At the moment we only support the ID registers for byte/word access.

     * This is not strictly correct as a few of the other registers also

     * allow byte access.

     */

    uint32_t offset = addr;

    if (offset >= 0xfe0) {

        if (offset & 3) {

            return 0;

        }

        return nvic_id[(offset - 0xfe0) >> 2];

    }

    if (size == 4) {

        return nvic_readl(opaque, offset);

    }

    hw_error("NVIC: Bad read of size %d at offset 0x%x\n", size, offset);

}


static void qemu_run_timers(QEMUClock *clock)

{

    QEMUTimer **ptimer_head, *ts;

    int64_t current_time;

    if (!clock->enabled)

        return;

    current_time = qemu_get_clock (clock);

    ptimer_head = &active_timers[clock->type];

    for(;;) {

        ts = *ptimer_head;

        if (!ts || ts->expire_time > current_time)

            break;

        /* remove timer from the list before calling the callback */

        *ptimer_head = ts->next;

        ts->next = NULL;

        /* run the callback (the timer list can be modified) */

        ts->cb(ts->opaque);

    }

}


static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,

                                  uint32_t val)

{

    cpu_outb(addr & IOPORTS_MASK, val);

}


void s390_sclp_extint(uint32_t parm)

{

    if (kvm_enabled()) {

        kvm_s390_service_interrupt(parm);

    } else {

        S390CPU *dummy_cpu = s390_cpu_addr2state(0);

        cpu_inject_ext(dummy_cpu, EXT_SERVICE, parm, 0);

    }

}


static int check_init_output_file(OutputFile *of, int file_index)

{

    int ret, i;

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

        OutputStream *ost = output_streams[of->ost_index + i];

        if (!ost->initialized)

            return 0;

    }

    of->ctx->interrupt_callback = int_cb;

    ret = avformat_write_header(of->ctx, &of->opts);

    if (ret < 0) {

        av_log(NULL, AV_LOG_ERROR,

               "Could not write header for output file #%d "

               "(incorrect codec parameters ?): %s\n",

               file_index, av_err2str(ret));

        return ret;

    }

    //assert_avoptions(of->opts);

    of->header_written = 1;

    av_dump_format(of->ctx, file_index, of->ctx->filename, 1);

    if (sdp_filename || want_sdp)

        print_sdp();

    /* flush the muxing queues */

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

        OutputStream *ost = output_streams[of->ost_index + i];

        /* try to improve muxing time_base (only possible if nothing has been written yet) */

        if (!av_fifo_size(ost->muxing_queue))

            ost->mux_timebase = ost->st->time_base;

        while (av_fifo_size(ost->muxing_queue)) {

            AVPacket pkt;

            av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL);

            write_packet(of, &pkt, ost);

        }

    }

    return 0;

}


static void colo_compare_connection(void *opaque, void *user_data)

{

    CompareState *s = user_data;

    Connection *conn = opaque;

    Packet *pkt = NULL;

    GList *result = NULL;

    int ret;

    while (!g_queue_is_empty(&conn->primary_list) &&

           !g_queue_is_empty(&conn->secondary_list)) {

        qemu_mutex_lock(&s->timer_check_lock);

        pkt = g_queue_pop_tail(&conn->primary_list);

        qemu_mutex_unlock(&s->timer_check_lock);

        result = g_queue_find_custom(&conn->secondary_list,

                              pkt, (GCompareFunc)colo_packet_compare_all);

        if (result) {

            ret = compare_chr_send(s->chr_out, pkt->data, pkt->size);

            if (ret < 0) {

                error_report("colo_send_primary_packet failed");

            }

            trace_colo_compare_main("packet same and release packet");

            g_queue_remove(&conn->secondary_list, result->data);

            packet_destroy(pkt, NULL);

        } else {

            /*

             * If one packet arrive late, the secondary_list or

             * primary_list will be empty, so we can't compare it

             * until next comparison.

             */

            trace_colo_compare_main("packet different");

            qemu_mutex_lock(&s->timer_check_lock);

            g_queue_push_tail(&conn->primary_list, pkt);

            qemu_mutex_unlock(&s->timer_check_lock);

            /* TODO: colo_notify_checkpoint();*/

            break;

        }

    }

}


int main_loop(void *opaque)

{

    struct pollfd ufds[3], *pf, *serial_ufd, *net_ufd, *gdb_ufd;

    int ret, n, timeout, serial_ok;

    uint8_t ch;

    CPUState *env = global_env;

    if (!term_inited) {

        /* initialize terminal only there so that the user has a

           chance to stop QEMU with Ctrl-C before the gdb connection

           is launched */

        term_inited = 1;

        term_init();

    }

    serial_ok = 1;

    cpu_enable_ticks();

    for(;;) {

        ret = cpu_x86_exec(env);

        if (reset_requested) {

            ret = EXCP_INTERRUPT;

            break;

        }

        if (ret == EXCP_DEBUG) {

            ret = EXCP_DEBUG;

            break;

        }

        /* if hlt instruction, we wait until the next IRQ */

        if (ret == EXCP_HLT)

            timeout = 10;

        else

            timeout = 0;

        /* poll any events */

        serial_ufd = NULL;

        pf = ufds;

        if (serial_ok && !(serial_ports[0].lsr & UART_LSR_DR)) {

            serial_ufd = pf;

            pf->fd = 0;

            pf->events = POLLIN;

            pf++;

        }

        net_ufd = NULL;

        if (net_fd > 0 && ne2000_can_receive(&ne2000_state)) {

            net_ufd = pf;

            pf->fd = net_fd;

            pf->events = POLLIN;

            pf++;

        }

        gdb_ufd = NULL;

        if (gdbstub_fd > 0) {

            gdb_ufd = pf;

            pf->fd = gdbstub_fd;

            pf->events = POLLIN;

            pf++;

        }

        ret = poll(ufds, pf - ufds, timeout);

        if (ret > 0) {

            if (serial_ufd && (serial_ufd->revents & POLLIN)) {

                n = read(0, &ch, 1);

                if (n == 1) {

                    serial_received_byte(&serial_ports[0], ch);

                } else {

		    /* Closed, stop polling. */

                    serial_ok = 0;

                }

            }

            if (net_ufd && (net_ufd->revents & POLLIN)) {

                uint8_t buf[MAX_ETH_FRAME_SIZE];

                n = read(net_fd, buf, MAX_ETH_FRAME_SIZE);

                if (n > 0) {

                    if (n < 60) {

                        memset(buf + n, 0, 60 - n);

                        n = 60;

                    }

                    ne2000_receive(&ne2000_state, buf, n);

                }

            }

            if (gdb_ufd && (gdb_ufd->revents & POLLIN)) {

                uint8_t buf[1];

                /* stop emulation if requested by gdb */

                n = read(gdbstub_fd, buf, 1);

                if (n == 1) {

                    ret = EXCP_INTERRUPT;

                    break;

                }

            }

        }

        /* timer IRQ */

        if (timer_irq_pending) {

            pic_set_irq(0, 1);

            pic_set_irq(0, 0);

            timer_irq_pending = 0;

            /* XXX: RTC test */

            if (cmos_data[RTC_REG_B] & 0x40) {

                pic_set_irq(8, 1);

            }

        }

        /* VGA */

        if (gui_refresh_pending) {

            display_state.dpy_refresh(&display_state);

            gui_refresh_pending = 0;

        }

    }

    cpu_disable_ticks();

    return ret;

}


static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,

                            int is_user, hwaddr *phys_ptr,

                            int *prot, target_ulong *page_size)

{

    CPUState *cs = CPU(arm_env_get_cpu(env));

    int code;

    uint32_t table;

    uint32_t desc;

    int type;

    int ap;

    int domain = 0;

    int domain_prot;

    hwaddr phys_addr;

    /* Pagetable walk.  */

    /* Lookup l1 descriptor.  */

    if (!get_level1_table_address(env, &table, address)) {

        /* Section translation fault if page walk is disabled by PD0 or PD1 */

        code = 5;

        goto do_fault;

    }

    desc = ldl_phys(cs->as, table);

    type = (desc & 3);

    domain = (desc >> 5) & 0x0f;

    domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;

    if (type == 0) {

        /* Section translation fault.  */

        code = 5;

        goto do_fault;

    }

    if (domain_prot == 0 || domain_prot == 2) {

        if (type == 2)

            code = 9; /* Section domain fault.  */

        else

            code = 11; /* Page domain fault.  */

        goto do_fault;

    }

    if (type == 2) {

        /* 1Mb section.  */

        phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);

        ap = (desc >> 10) & 3;

        code = 13;

        *page_size = 1024 * 1024;

    } else {

        /* Lookup l2 entry.  */

	if (type == 1) {

	    /* Coarse pagetable.  */

	    table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);

	} else {

	    /* Fine pagetable.  */

	    table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);

	}

        desc = ldl_phys(cs->as, table);

        switch (desc & 3) {

        case 0: /* Page translation fault.  */

            code = 7;

            goto do_fault;

        case 1: /* 64k page.  */

            phys_addr = (desc & 0xffff0000) | (address & 0xffff);

            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;

            *page_size = 0x10000;

            break;

        case 2: /* 4k page.  */

            phys_addr = (desc & 0xfffff000) | (address & 0xfff);

            ap = (desc >> (4 + ((address >> 9) & 6))) & 3;

            *page_size = 0x1000;

            break;

        case 3: /* 1k page.  */

	    if (type == 1) {

		if (arm_feature(env, ARM_FEATURE_XSCALE)) {

		    phys_addr = (desc & 0xfffff000) | (address & 0xfff);

		} else {

		    /* Page translation fault.  */

		    code = 7;

		    goto do_fault;

		}

	    } else {

		phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);

	    }

            ap = (desc >> 4) & 3;

            *page_size = 0x400;

            break;

        default:

            /* Never happens, but compiler isn't smart enough to tell.  */

            abort();

        }

        code = 15;

    }

    *prot = check_ap(env, ap, domain_prot, access_type, is_user);

    if (!*prot) {

        /* Access permission fault.  */

        goto do_fault;

    }

    *prot |= PAGE_EXEC;

    *phys_ptr = phys_addr;

    return 0;

do_fault:

    return code | (domain << 4);

}


static void an5206_init(QEMUMachineInitArgs *args)

{

    ram_addr_t ram_size = args->ram_size;

    const char *cpu_model = args->cpu_model;

    const char *kernel_filename = args->kernel_filename;

    CPUM68KState *env;

    int kernel_size;

    uint64_t elf_entry;

    target_phys_addr_t entry;

    MemoryRegion *address_space_mem = get_system_memory();

    MemoryRegion *ram = g_new(MemoryRegion, 1);

    MemoryRegion *sram = g_new(MemoryRegion, 1);

    if (!cpu_model)

        cpu_model = "m5206";

    env = cpu_init(cpu_model);

    if (!env) {

        hw_error("Unable to find m68k CPU definition\n");

    }

    /* Initialize CPU registers.  */

    env->vbr = 0;

    /* TODO: allow changing MBAR and RAMBAR.  */

    env->mbar = AN5206_MBAR_ADDR | 1;

    env->rambar0 = AN5206_RAMBAR_ADDR | 1;

    /* DRAM at address zero */

    memory_region_init_ram(ram, "an5206.ram", ram_size);

    vmstate_register_ram_global(ram);

    memory_region_add_subregion(address_space_mem, 0, ram);

    /* Internal SRAM.  */

    memory_region_init_ram(sram, "an5206.sram", 512);

    vmstate_register_ram_global(sram);

    memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);

    mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, env);

    /* Load kernel.  */

    if (!kernel_filename) {

        fprintf(stderr, "Kernel image must be specified\n");

        exit(1);

    }

    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,

                           NULL, NULL, 1, ELF_MACHINE, 0);

    entry = elf_entry;

    if (kernel_size < 0) {

        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);

    }

    if (kernel_size < 0) {

        kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,

                                          ram_size - KERNEL_LOAD_ADDR);

        entry = KERNEL_LOAD_ADDR;

    }

    if (kernel_size < 0) {

        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);

        exit(1);

    }

    env->pc = entry;

}


int cpu_x86_signal_handler(int host_signum, struct siginfo *info,

                           void *puc)

{

    uint32_t *regs = (uint32_t *)(info + 1);

    void *sigmask = (regs + 20);

    unsigned long pc;

    int is_write;

    uint32_t insn;

    /* XXX: is there a standard glibc define ? */

    pc = regs[1];

    /* XXX: need kernel patch to get write flag faster */

    is_write = 0;

    insn = *(uint32_t *)pc;

    if ((insn >> 30) == 3) {

      switch((insn >> 19) & 0x3f) {

      case 0x05: // stb

      case 0x06: // sth

      case 0x04: // st

      case 0x07: // std

      case 0x24: // stf

      case 0x27: // stdf

      case 0x25: // stfsr

	is_write = 1;

	break;

      }

    }

    return handle_cpu_signal(pc, (unsigned long)info->si_addr,

                             is_write, sigmask);

}


static void test_visitor_out_native_list_number(TestOutputVisitorData *data,

                                                const void *unused)

{

    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);

}


static int read_uncompressed_sgi(unsigned char* out_buf, SgiState *s)

{

    int x, y, z;

    unsigned int offset = s->height * s->width * s->bytes_per_channel;

    GetByteContext gp[4];

    uint8_t *out_end;

    /* Test buffer size. */

    if (offset * s->depth > bytestream2_get_bytes_left(&s->g))

        return AVERROR_INVALIDDATA;

    /* Create a reader for each plane */

    for (z = 0; z < s->depth; z++) {

        gp[z] = s->g;

        bytestream2_skip(&gp[z], z * offset);

    }

    for (y = s->height - 1; y >= 0; y--) {

        out_end = out_buf + (y * s->linesize);

        if (s->bytes_per_channel == 1) {

            for (x = s->width; x > 0; x--) {

                bytestream2_get_bufferu(&gp[z], out_end, s->depth);

                out_end += s->depth;

            }

        } else {

            uint16_t *out16 = (uint16_t *)out_end;

            for (x = s->width; x > 0; x--)

                for (z = 0; z < s->depth; z++)

                    *out16++ = bytestream2_get_ne16u(&gp[z]);

        }

    }

    return 0;

}


static void rtas_ibm_configure_connector(PowerPCCPU *cpu,

                                         sPAPRMachineState *spapr,

                                         uint32_t token, uint32_t nargs,

                                         target_ulong args, uint32_t nret,

                                         target_ulong rets)

{

    uint64_t wa_addr;

    uint64_t wa_offset;

    uint32_t drc_index;

    sPAPRDRConnector *drc;

    sPAPRDRConnectorClass *drck;

    sPAPRConfigureConnectorState *ccs;

    sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;

    int rc;

    const void *fdt;

    if (nargs != 2 || nret != 1) {

        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);

        return;

    wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);

    drc_index = rtas_ld(wa_addr, 0);

    drc = spapr_dr_connector_by_index(drc_index);

    if (!drc) {

        DPRINTF("rtas_ibm_configure_connector: invalid DRC index: %xh\n",

        rc = RTAS_OUT_PARAM_ERROR;

    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    fdt = drck->get_fdt(drc, NULL);

    ccs = spapr_ccs_find(spapr, drc_index);

    if (!ccs) {

        ccs = g_new0(sPAPRConfigureConnectorState, 1);

        (void)drck->get_fdt(drc, &ccs->fdt_offset);

        ccs->drc_index = drc_index;

        spapr_ccs_add(spapr, ccs);

    do {

        uint32_t tag;

        const char *name;

        const struct fdt_property *prop;

        int fdt_offset_next, prop_len;

        tag = fdt_next_tag(fdt, ccs->fdt_offset, &fdt_offset_next);

        switch (tag) {

        case FDT_BEGIN_NODE:

            ccs->fdt_depth++;

            name = fdt_get_name(fdt, ccs->fdt_offset, NULL);

            /* provide the name of the next OF node */

            wa_offset = CC_VAL_DATA_OFFSET;

            rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);

            rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,

                                  (uint8_t *)name, strlen(name) + 1);

            resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;

            break;

        case FDT_END_NODE:

            ccs->fdt_depth--;

            if (ccs->fdt_depth == 0) {

                /* done sending the device tree, don't need to track

                 * the state anymore

                 */

                drck->set_configured(drc);

                spapr_ccs_remove(spapr, ccs);

                ccs = NULL;

                resp = SPAPR_DR_CC_RESPONSE_SUCCESS;

            } else {

                resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;

            break;

        case FDT_PROP:

            prop = fdt_get_property_by_offset(fdt, ccs->fdt_offset,

                                              &prop_len);

            name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));

            /* provide the name of the next OF property */

            wa_offset = CC_VAL_DATA_OFFSET;

            rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);

            rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,

                                  (uint8_t *)name, strlen(name) + 1);

            /* provide the length and value of the OF property. data gets

             * placed immediately after NULL terminator of the OF property's

             * name string

             */

            wa_offset += strlen(name) + 1,

            rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);

            rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);

            rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,

                                  (uint8_t *)((struct fdt_property *)prop)->data,

                                  prop_len);

            resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;

            break;

        case FDT_END:

            resp = SPAPR_DR_CC_RESPONSE_ERROR;

        default:

            /* keep seeking for an actionable tag */

            break;

        if (ccs) {

            ccs->fdt_offset = fdt_offset_next;

    } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);

    rc = resp;

out:

    rtas_st(rets, 0, rc);


static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)

{

    BDRVBochsState *s = bs->opaque;

    int64_t offset = sector_num * 512;

    int64_t extent_index, extent_offset, bitmap_offset;

    char bitmap_entry;

    // seek to sector

    extent_index = offset / s->extent_size;

    extent_offset = (offset % s->extent_size) / 512;

    if (s->catalog_bitmap[extent_index] == 0xffffffff) {

	return -1; /* not allocated */

    }

    bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *

	(s->extent_blocks + s->bitmap_blocks));

    /* read in bitmap for current extent */

    if (bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),

                   &bitmap_entry, 1) != 1) {

        return -1;

    }

    if (!((bitmap_entry >> (extent_offset % 8)) & 1)) {

	return -1; /* not allocated */

    }

    return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));

}


static int decode_fctl_chunk(AVFormatContext *s, APNGDemuxContext *ctx, AVPacket *pkt)

{

    uint32_t sequence_number, width, height, x_offset, y_offset;

    uint16_t delay_num, delay_den;

    uint8_t dispose_op, blend_op;

    sequence_number = avio_rb32(s->pb);

    width           = avio_rb32(s->pb);

    height          = avio_rb32(s->pb);

    x_offset        = avio_rb32(s->pb);

    y_offset        = avio_rb32(s->pb);

    delay_num       = avio_rb16(s->pb);

    delay_den       = avio_rb16(s->pb);

    dispose_op      = avio_r8(s->pb);

    blend_op        = avio_r8(s->pb);

    avio_skip(s->pb, 4); /* crc */

    /* default is hundredths of seconds */

    if (!delay_den)

        delay_den = 100;

    if (!delay_num || delay_den / delay_num > ctx->max_fps) {

        delay_num = 1;

        delay_den = ctx->default_fps;

    }

    ctx->pkt_duration = av_rescale_q(delay_num,

                                     (AVRational){ 1, delay_den },

                                     s->streams[0]->time_base);

    av_log(s, AV_LOG_DEBUG, "%s: "

            "sequence_number: %"PRId32", "

            "width: %"PRIu32", "

            "height: %"PRIu32", "

            "x_offset: %"PRIu32", "

            "y_offset: %"PRIu32", "

            "delay_num: %"PRIu16", "

            "delay_den: %"PRIu16", "

            "dispose_op: %d, "

            "blend_op: %d\n",

            __FUNCTION__,

            sequence_number,

            width,

            height,

            x_offset,

            y_offset,

            delay_num,

            delay_den,

            dispose_op,

            blend_op);

    if (width != s->streams[0]->codecpar->width ||

        height != s->streams[0]->codecpar->height ||

        x_offset != 0 ||

        y_offset != 0) {

        if (sequence_number == 0 ||

            x_offset >= s->streams[0]->codecpar->width ||

            width > s->streams[0]->codecpar->width - x_offset ||

            y_offset >= s->streams[0]->codecpar->height ||

            height > s->streams[0]->codecpar->height - y_offset)

            return AVERROR_INVALIDDATA;

        ctx->is_key_frame = 0;

    } else {

        if (sequence_number == 0 && dispose_op == APNG_DISPOSE_OP_PREVIOUS)

            dispose_op = APNG_DISPOSE_OP_BACKGROUND;

        ctx->is_key_frame = dispose_op == APNG_DISPOSE_OP_BACKGROUND ||

                            blend_op   == APNG_BLEND_OP_SOURCE;

    }

    return 0;

}


static int ape_tag_read_field(AVFormatContext *s)

{

    AVIOContext *pb = s->pb;

    uint8_t key[1024], *value;

    uint32_t size, flags;

    int i, c;

    size = avio_rl32(pb);  /* field size */

    flags = avio_rl32(pb); /* field flags */

    for (i = 0; i < sizeof(key) - 1; i++) {

        c = avio_r8(pb);

        if (c < 0x20 || c > 0x7E)

            break;

        else

            key[i] = c;

    }

    key[i] = 0;

    if (c != 0) {

        av_log(s, AV_LOG_WARNING, "Invalid APE tag key '%s'.\n", key);

        return -1;

    }

    if (size > INT32_MAX - FF_INPUT_BUFFER_PADDING_SIZE) {

        av_log(s, AV_LOG_ERROR, "APE tag size too large.\n");

        return AVERROR_INVALIDDATA;

    }

    if (flags & APE_TAG_FLAG_IS_BINARY) {

        uint8_t filename[1024];

        enum AVCodecID id;

        AVStream *st = avformat_new_stream(s, NULL);

        if (!st)

            return AVERROR(ENOMEM);

        size -= avio_get_str(pb, size, filename, sizeof(filename));

        if (size <= 0) {

            av_log(s, AV_LOG_WARNING, "Skipping binary tag '%s'.\n", key);

            return 0;

        }

        av_dict_set(&st->metadata, key, filename, 0);

        if ((id = ff_guess_image2_codec(filename)) != AV_CODEC_ID_NONE) {

            AVPacket pkt;

            int ret;

            ret = av_get_packet(s->pb, &pkt, size);

            if (ret < 0) {

                av_log(s, AV_LOG_ERROR, "Error reading cover art.\n");

                return ret;

            }

            st->disposition      |= AV_DISPOSITION_ATTACHED_PIC;

            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;

            st->codec->codec_id   = id;

            st->attached_pic              = pkt;

            st->attached_pic.stream_index = st->index;

            st->attached_pic.flags       |= AV_PKT_FLAG_KEY;

        } else {

            if (ff_get_extradata(st->codec, s->pb, size) < 0)

                return AVERROR(ENOMEM);

            st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;

        }

    } else {

        value = av_malloc(size+1);

        if (!value)

            return AVERROR(ENOMEM);

        c = avio_read(pb, value, size);

        if (c < 0) {

            av_free(value);

            return c;

        }

        value[c] = 0;

        av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL);

    }

    return 0;

}


static inline void RENAME(rgb2rgb_init)(void)

{

    rgb15to16       = RENAME(rgb15to16);

    rgb15tobgr24    = RENAME(rgb15tobgr24);

    rgb15to32       = RENAME(rgb15to32);

    rgb16tobgr24    = RENAME(rgb16tobgr24);

    rgb16to32       = RENAME(rgb16to32);

    rgb16to15       = RENAME(rgb16to15);

    rgb24tobgr16    = RENAME(rgb24tobgr16);

    rgb24tobgr15    = RENAME(rgb24tobgr15);

    rgb24tobgr32    = RENAME(rgb24tobgr32);

    rgb32to16       = RENAME(rgb32to16);

    rgb32to15       = RENAME(rgb32to15);

    rgb32tobgr24    = RENAME(rgb32tobgr24);

    rgb24to15       = RENAME(rgb24to15);

    rgb24to16       = RENAME(rgb24to16);

    rgb24tobgr24    = RENAME(rgb24tobgr24);

    shuffle_bytes_2103 = RENAME(shuffle_bytes_2103);

    rgb32tobgr16    = RENAME(rgb32tobgr16);

    rgb32tobgr15    = RENAME(rgb32tobgr15);

    yv12toyuy2      = RENAME(yv12toyuy2);

    yv12touyvy      = RENAME(yv12touyvy);

    yuv422ptoyuy2   = RENAME(yuv422ptoyuy2);

    yuv422ptouyvy   = RENAME(yuv422ptouyvy);

    yuy2toyv12      = RENAME(yuy2toyv12);

    planar2x        = RENAME(planar2x);

    rgb24toyv12     = RENAME(rgb24toyv12);

    interleaveBytes = RENAME(interleaveBytes);

    vu9_to_vu12     = RENAME(vu9_to_vu12);

    yvu9_to_yuy2    = RENAME(yvu9_to_yuy2);

    uyvytoyuv420    = RENAME(uyvytoyuv420);

    uyvytoyuv422    = RENAME(uyvytoyuv422);

    yuyvtoyuv420    = RENAME(yuyvtoyuv420);

    yuyvtoyuv422    = RENAME(yuyvtoyuv422);

}


static av_always_inline int vc1_filter_line(uint8_t* src, int stride, int pq){

    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;

    int a0 = (2*(src[-2*stride] - src[ 1*stride]) - 5*(src[-1*stride] - src[ 0*stride]) + 4) >> 3;

    int a0_sign = a0 >> 31;        /* Store sign */

    a0 = (a0 ^ a0_sign) - a0_sign; /* a0 = FFABS(a0); */

    if(a0 < pq){

        int a1 = FFABS((2*(src[-4*stride] - src[-1*stride]) - 5*(src[-3*stride] - src[-2*stride]) + 4) >> 3);

        int a2 = FFABS((2*(src[ 0*stride] - src[ 3*stride]) - 5*(src[ 1*stride] - src[ 2*stride]) + 4) >> 3);

        if(a1 < a0 || a2 < a0){

            int clip = src[-1*stride] - src[ 0*stride];

            int clip_sign = clip >> 31;

            clip = ((clip ^ clip_sign) - clip_sign)>>1;

            if(clip){

                int a3 = FFMIN(a1, a2);

                int d = 5 * (a3 - a0);

                int d_sign = (d >> 31);

                d = ((d ^ d_sign) - d_sign) >> 3;

                d_sign ^= a0_sign;

                if( d_sign ^ clip_sign )

                    d = 0;

                else{

                    d = FFMIN(d, clip);

                    d = (d ^ d_sign) - d_sign;          /* Restore sign */

                    src[-1*stride] = cm[src[-1*stride] - d];

                    src[ 0*stride] = cm[src[ 0*stride] + d];

                }

                return 1;

            }

        }

    }

    return 0;

}


static av_cold void RENAME(sws_init_swScale)(SwsContext *c)

{

    enum PixelFormat srcFormat = c->srcFormat,

                     dstFormat = c->dstFormat;

    if (!is16BPS(dstFormat) && !is9_OR_10BPS(dstFormat)) {

        if (!(c->flags & SWS_BITEXACT)) {

            if (c->flags & SWS_ACCURATE_RND) {

                c->yuv2yuv1 = RENAME(yuv2yuv1_ar    );

                c->yuv2yuvX = RENAME(yuv2yuvX_ar    );

                if (!(c->flags & SWS_FULL_CHR_H_INT)) {

                    switch (c->dstFormat) {

                    case PIX_FMT_RGB32:   c->yuv2packedX = RENAME(yuv2rgb32_X_ar);   break;

                    case PIX_FMT_BGR24:   c->yuv2packedX = RENAME(yuv2bgr24_X_ar);   break;

                    case PIX_FMT_RGB555:  c->yuv2packedX = RENAME(yuv2rgb555_X_ar);  break;

                    case PIX_FMT_RGB565:  c->yuv2packedX = RENAME(yuv2rgb565_X_ar);  break;

                    case PIX_FMT_YUYV422: c->yuv2packedX = RENAME(yuv2yuyv422_X_ar); break;

                    default: break;

                    }

                }

            } else {

                c->yuv2yuv1 = RENAME(yuv2yuv1    );

                c->yuv2yuvX = RENAME(yuv2yuvX    );

                if (!(c->flags & SWS_FULL_CHR_H_INT)) {

                    switch (c->dstFormat) {

                    case PIX_FMT_RGB32:   c->yuv2packedX = RENAME(yuv2rgb32_X);   break;

                    case PIX_FMT_BGR24:   c->yuv2packedX = RENAME(yuv2bgr24_X);   break;

                    case PIX_FMT_RGB555:  c->yuv2packedX = RENAME(yuv2rgb555_X);  break;

                    case PIX_FMT_RGB565:  c->yuv2packedX = RENAME(yuv2rgb565_X);  break;

                    case PIX_FMT_YUYV422: c->yuv2packedX = RENAME(yuv2yuyv422_X); break;

                    default: break;

                    }

                }

            }

        }

        if (!(c->flags & SWS_FULL_CHR_H_INT)) {

            switch (c->dstFormat) {

            case PIX_FMT_RGB32:

                c->yuv2packed1 = RENAME(yuv2rgb32_1);

                c->yuv2packed2 = RENAME(yuv2rgb32_2);

                break;

            case PIX_FMT_BGR24:

                c->yuv2packed1 = RENAME(yuv2bgr24_1);

                c->yuv2packed2 = RENAME(yuv2bgr24_2);

                break;

            case PIX_FMT_RGB555:

                c->yuv2packed1 = RENAME(yuv2rgb555_1);

                c->yuv2packed2 = RENAME(yuv2rgb555_2);

                break;

            case PIX_FMT_RGB565:

                c->yuv2packed1 = RENAME(yuv2rgb565_1);

                c->yuv2packed2 = RENAME(yuv2rgb565_2);

                break;

            case PIX_FMT_YUYV422:

                c->yuv2packed1 = RENAME(yuv2yuyv422_1);

                c->yuv2packed2 = RENAME(yuv2yuyv422_2);

                break;

            default:

                break;

            }

        }

    }

#if !COMPILE_TEMPLATE_MMX2

    c->hScale       = RENAME(hScale      );

#endif /* !COMPILE_TEMPLATE_MMX2 */

    // Use the new MMX scaler if the MMX2 one can't be used (it is faster than the x86 ASM one).

#if COMPILE_TEMPLATE_MMX2

    if (c->flags & SWS_FAST_BILINEAR && c->canMMX2BeUsed)

    {

        c->hyscale_fast = RENAME(hyscale_fast);

        c->hcscale_fast = RENAME(hcscale_fast);

    } else {

#endif /* COMPILE_TEMPLATE_MMX2 */

        c->hyscale_fast = NULL;

        c->hcscale_fast = NULL;

#if COMPILE_TEMPLATE_MMX2

    }

#endif /* COMPILE_TEMPLATE_MMX2 */

#if !COMPILE_TEMPLATE_MMX2

    switch(srcFormat) {

        case PIX_FMT_YUYV422  : c->chrToYV12 = RENAME(yuy2ToUV); break;

        case PIX_FMT_UYVY422  : c->chrToYV12 = RENAME(uyvyToUV); break;

        case PIX_FMT_NV12     : c->chrToYV12 = RENAME(nv12ToUV); break;

        case PIX_FMT_NV21     : c->chrToYV12 = RENAME(nv21ToUV); break;

        case PIX_FMT_YUV420P16BE:

        case PIX_FMT_YUV422P16BE:

        case PIX_FMT_YUV444P16BE: c->chrToYV12 = RENAME(BEToUV); break;

        case PIX_FMT_YUV420P16LE:

        case PIX_FMT_YUV422P16LE:

        case PIX_FMT_YUV444P16LE: c->chrToYV12 = RENAME(LEToUV); break;

        default: break;

    }

#endif /* !COMPILE_TEMPLATE_MMX2 */

    if (!c->chrSrcHSubSample) {

        switch(srcFormat) {

        case PIX_FMT_BGR24  : c->chrToYV12 = RENAME(bgr24ToUV); break;

        case PIX_FMT_RGB24  : c->chrToYV12 = RENAME(rgb24ToUV); break;

        default: break;

        }

    }

    switch (srcFormat) {

#if !COMPILE_TEMPLATE_MMX2

    case PIX_FMT_YUYV422  :

    case PIX_FMT_YUV420P16BE:

    case PIX_FMT_YUV422P16BE:

    case PIX_FMT_YUV444P16BE:

    case PIX_FMT_Y400A    :

    case PIX_FMT_GRAY16BE : c->lumToYV12 = RENAME(yuy2ToY); break;

    case PIX_FMT_UYVY422  :

    case PIX_FMT_YUV420P16LE:

    case PIX_FMT_YUV422P16LE:

    case PIX_FMT_YUV444P16LE:

    case PIX_FMT_GRAY16LE : c->lumToYV12 = RENAME(uyvyToY); break;

#endif /* !COMPILE_TEMPLATE_MMX2 */

    case PIX_FMT_BGR24    : c->lumToYV12 = RENAME(bgr24ToY); break;

    case PIX_FMT_RGB24    : c->lumToYV12 = RENAME(rgb24ToY); break;

    default: break;

    }

#if !COMPILE_TEMPLATE_MMX2

    if (c->alpPixBuf) {

        switch (srcFormat) {

        case PIX_FMT_Y400A  : c->alpToYV12 = RENAME(yuy2ToY); break;

        default: break;

        }

    }

#endif /* !COMPILE_TEMPLATE_MMX2 */

}


static void new_subtitle_stream(AVFormatContext *oc)

{

    AVStream *st;

    AVCodec *codec=NULL;

    AVCodecContext *subtitle_enc;

    st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);

    if (!st) {

        fprintf(stderr, "Could not alloc stream\n");

        ffmpeg_exit(1);

    }

    subtitle_enc = st->codec;

    output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);

    if(!subtitle_stream_copy){

        subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1,

                                                   avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);

        codec= output_codecs[nb_output_codecs-1] = avcodec_find_encoder_by_name(subtitle_codec_name);

    }

    avcodec_get_context_defaults3(st->codec, codec);

    bitstream_filters[nb_output_files] =

        grow_array(bitstream_filters[nb_output_files],

                   sizeof(*bitstream_filters[nb_output_files]),

                   &nb_bitstream_filters[nb_output_files], oc->nb_streams);

    bitstream_filters[nb_output_files][oc->nb_streams - 1]= subtitle_bitstream_filters;

    subtitle_bitstream_filters= NULL;

    subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;

    if(subtitle_codec_tag)

        subtitle_enc->codec_tag= subtitle_codec_tag;

    if (subtitle_stream_copy) {

        st->stream_copy = 1;

    } else {

        set_context_opts(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);

    }

    if (subtitle_language) {

        av_metadata_set2(&st->metadata, "language", subtitle_language, 0);

        av_freep(&subtitle_language);

    }

    subtitle_disable = 0;

    av_freep(&subtitle_codec_name);

    subtitle_stream_copy = 0;

}