static int set_params(AVFilterContext *ctx, const char *params)

{

    Frei0rContext *s = ctx->priv;

    int i;

    if (!params)

        return 0;

    for (i = 0; i < s->plugin_info.num_params; i++) {

        f0r_param_info_t info;

        char *param;

        int ret;

        s->get_param_info(&info, i);

        if (*params) {

            if (!(param = av_get_token(&params, "|")))

                return AVERROR(ENOMEM);

            params++;               /* skip ':' */

            ret = set_param(ctx, info, i, param);

            av_free(param);

            if (ret < 0)

                return ret;

        }

        av_log(ctx, AV_LOG_VERBOSE,

               "idx:%d name:'%s' type:%s explanation:'%s' ",

               i, info.name,

               info.type == F0R_PARAM_BOOL     ? "bool"     :

               info.type == F0R_PARAM_DOUBLE   ? "double"   :

               info.type == F0R_PARAM_COLOR    ? "color"    :

               info.type == F0R_PARAM_POSITION ? "position" :

               info.type == F0R_PARAM_STRING   ? "string"   : "unknown",

               info.explanation);

#ifdef DEBUG

        av_log(ctx, AV_LOG_DEBUG, "value:");

        switch (info.type) {

            void *v;

            double d;

            char s[128];

            f0r_param_color_t col;

            f0r_param_position_t pos;

        case F0R_PARAM_BOOL:

            v = &d;

            s->get_param_value(s->instance, v, i);

            av_log(ctx, AV_LOG_DEBUG, "%s", d >= 0.5 && d <= 1.0 ? "y" : "n");

            break;

        case F0R_PARAM_DOUBLE:

            v = &d;

            s->get_param_value(s->instance, v, i);

            av_log(ctx, AV_LOG_DEBUG, "%f", d);

            break;

        case F0R_PARAM_COLOR:

            v = &col;

            s->get_param_value(s->instance, v, i);

            av_log(ctx, AV_LOG_DEBUG, "%f/%f/%f", col.r, col.g, col.b);

            break;

        case F0R_PARAM_POSITION:

            v = &pos;

            s->get_param_value(s->instance, v, i);

            av_log(ctx, AV_LOG_DEBUG, "%f/%f", pos.x, pos.y);

            break;

        default: /* F0R_PARAM_STRING */

            v = s;

            s->get_param_value(s->instance, v, i);

            av_log(ctx, AV_LOG_DEBUG, "'%s'\n", s);

            break;

        }

#endif

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

    }

    return 0;

}


static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)

{

    int y;

    unsigned char pix;

    /* 1-color encoding: the whole block is 1 solid color */

    CHECK_STREAM_PTR(1);

    pix = *s->stream_ptr++;

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

        memset(s->pixel_ptr, pix, 8);

        s->pixel_ptr += s->stride;

    }

    /* report success */

    return 0;

}


static int ra144_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,

                              const AVFrame *frame, int *got_packet_ptr)

{

    static const uint8_t sizes[LPC_ORDER] = {64, 32, 32, 16, 16, 8, 8, 8, 8, 4};

    static const uint8_t bit_sizes[LPC_ORDER] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2};

    RA144Context *ractx = avctx->priv_data;

    PutBitContext pb;

    int32_t lpc_data[NBLOCKS * BLOCKSIZE];

    int32_t lpc_coefs[LPC_ORDER][MAX_LPC_ORDER];

    int shift[LPC_ORDER];

    int16_t block_coefs[NBLOCKS][LPC_ORDER];

    int lpc_refl[LPC_ORDER];    /**< reflection coefficients of the frame */

    unsigned int refl_rms[NBLOCKS]; /**< RMS of the reflection coefficients */

    const int16_t *samples = frame ? (const int16_t *)frame->data[0] : NULL;

    int energy = 0;

    int i, idx, ret;

    if (ractx->last_frame)

        return 0;

    if ((ret = ff_alloc_packet2(avctx, avpkt, FRAMESIZE)))

        return ret;

    /**

     * Since the LPC coefficients are calculated on a frame centered over the

     * fourth subframe, to encode a given frame, data from the next frame is

     * needed. In each call to this function, the previous frame (whose data are

     * saved in the encoder context) is encoded, and data from the current frame

     * are saved in the encoder context to be used in the next function call.

     */

    for (i = 0; i < (2 * BLOCKSIZE + BLOCKSIZE / 2); i++) {

        lpc_data[i] = ractx->curr_block[BLOCKSIZE + BLOCKSIZE / 2 + i];

        energy += (lpc_data[i] * lpc_data[i]) >> 4;

    }

    if (frame) {

        int j;

        for (j = 0; j < frame->nb_samples && i < NBLOCKS * BLOCKSIZE; i++, j++) {

            lpc_data[i] = samples[j] >> 2;

            energy += (lpc_data[i] * lpc_data[i]) >> 4;

        }

    }

    if (i < NBLOCKS * BLOCKSIZE)

        memset(&lpc_data[i], 0, (NBLOCKS * BLOCKSIZE - i) * sizeof(*lpc_data));

    energy = ff_energy_tab[quantize(ff_t_sqrt(energy >> 5) >> 10, ff_energy_tab,

                                    32)];

    ff_lpc_calc_coefs(&ractx->lpc_ctx, lpc_data, NBLOCKS * BLOCKSIZE, LPC_ORDER,

                      LPC_ORDER, 16, lpc_coefs, shift, FF_LPC_TYPE_LEVINSON,

                      0, ORDER_METHOD_EST, 12, 0);

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

        block_coefs[NBLOCKS - 1][i] = -(lpc_coefs[LPC_ORDER - 1][i] <<

                                        (12 - shift[LPC_ORDER - 1]));

    /**

     * TODO: apply perceptual weighting of the input speech through bandwidth

     * expansion of the LPC filter.

     */

    if (ff_eval_refl(lpc_refl, block_coefs[NBLOCKS - 1], avctx)) {

        /**

         * The filter is unstable: use the coefficients of the previous frame.

         */

        ff_int_to_int16(block_coefs[NBLOCKS - 1], ractx->lpc_coef[1]);

        if (ff_eval_refl(lpc_refl, block_coefs[NBLOCKS - 1], avctx)) {

            /* the filter is still unstable. set reflection coeffs to zero. */

            memset(lpc_refl, 0, sizeof(lpc_refl));

        }

    }

    init_put_bits(&pb, avpkt->data, avpkt->size);

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

        idx = quantize(lpc_refl[i], ff_lpc_refl_cb[i], sizes[i]);

        put_bits(&pb, bit_sizes[i], idx);

        lpc_refl[i] = ff_lpc_refl_cb[i][idx];

    }

    ractx->lpc_refl_rms[0] = ff_rms(lpc_refl);

    ff_eval_coefs(ractx->lpc_coef[0], lpc_refl);

    refl_rms[0] = ff_interp(ractx, block_coefs[0], 1, 1, ractx->old_energy);

    refl_rms[1] = ff_interp(ractx, block_coefs[1], 2,

                            energy <= ractx->old_energy,

                            ff_t_sqrt(energy * ractx->old_energy) >> 12);

    refl_rms[2] = ff_interp(ractx, block_coefs[2], 3, 0, energy);

    refl_rms[3] = ff_rescale_rms(ractx->lpc_refl_rms[0], energy);

    ff_int_to_int16(block_coefs[NBLOCKS - 1], ractx->lpc_coef[0]);

    put_bits(&pb, 5, quantize(energy, ff_energy_tab, 32));

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

        ra144_encode_subblock(ractx, ractx->curr_block + i * BLOCKSIZE,

                              block_coefs[i], refl_rms[i], &pb);

    flush_put_bits(&pb);

    ractx->old_energy = energy;

    ractx->lpc_refl_rms[1] = ractx->lpc_refl_rms[0];

    FFSWAP(unsigned int *, ractx->lpc_coef[0], ractx->lpc_coef[1]);

    /* copy input samples to current block for processing in next call */

    i = 0;

    if (frame) {

        for (; i < frame->nb_samples; i++)

            ractx->curr_block[i] = samples[i] >> 2;

        if ((ret = ff_af_queue_add(&ractx->afq, frame)) < 0)

            return ret;

    } else

        ractx->last_frame = 1;

    memset(&ractx->curr_block[i], 0,

           (NBLOCKS * BLOCKSIZE - i) * sizeof(*ractx->curr_block));

    /* Get the next frame pts/duration */

    ff_af_queue_remove(&ractx->afq, avctx->frame_size, &avpkt->pts,

                       &avpkt->duration);

    avpkt->size = FRAMESIZE;

    *got_packet_ptr = 1;

    return 0;

}


static off_t read_uint32(int fd, int64_t offset)

{

	uint32_t buffer;

	if (pread(fd, &buffer, 4, offset) < 4)

		return 0;

	return be32_to_cpu(buffer);

}


static int tosa_dac_send(I2CSlave *i2c, uint8_t data)

{

    TosaDACState *s = TOSA_DAC(i2c);

    s->buf[s->len] = data;

    if (s->len ++ > 2) {

#ifdef VERBOSE

        fprintf(stderr, "%s: message too long (%i bytes)\n", __FUNCTION__, s->len);

#endif

        return 1;

    }

    if (s->len == 2) {

        fprintf(stderr, "dac: channel %d value 0x%02x\n",

                s->buf[0], s->buf[1]);

    }

    return 0;

}


static void socket_start_incoming_migration(SocketAddress *saddr,

                                            Error **errp)

{

    QIOChannelSocket *listen_ioc = qio_channel_socket_new();

    qio_channel_set_name(QIO_CHANNEL(listen_ioc),

                         "migration-socket-listener");

    if (qio_channel_socket_listen_sync(listen_ioc, saddr, errp) < 0) {

        object_unref(OBJECT(listen_ioc));

        qapi_free_SocketAddress(saddr);

        return;

    }

    qio_channel_add_watch(QIO_CHANNEL(listen_ioc),

                          G_IO_IN,

                          socket_accept_incoming_migration,

                          listen_ioc,

                          (GDestroyNotify)object_unref);

    qapi_free_SocketAddress(saddr);

}


static void mpc8544ds_init(ram_addr_t ram_size,

                         const char *boot_device,

                         const char *kernel_filename,

                         const char *kernel_cmdline,

                         const char *initrd_filename,

                         const char *cpu_model)

{

    PCIBus *pci_bus;

    CPUState *env;

    uint64_t elf_entry;

    uint64_t elf_lowaddr;

    target_phys_addr_t entry=0;

    target_phys_addr_t loadaddr=UIMAGE_LOAD_BASE;

    target_long kernel_size=0;

    target_ulong dt_base=DTB_LOAD_BASE;

    target_ulong initrd_base=INITRD_LOAD_BASE;

    target_long initrd_size=0;

    void *fdt;

    int i=0;

    unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};

    qemu_irq *irqs, *mpic, *pci_irqs;

    SerialState * serial[2];

    /* Setup CPU */

    env = cpu_ppc_init("e500v2_v30");

    if (!env) {

        fprintf(stderr, "Unable to initialize CPU!\n");

        exit(1);

    }

    /* Fixup Memory size on a alignment boundary */

    ram_size &= ~(RAM_SIZES_ALIGN - 1);

    /* Register Memory */

    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(ram_size));

    /* MPIC */

    irqs = qemu_mallocz(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);

    irqs[OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_INT];

    irqs[OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_CINT];

    mpic = mpic_init(MPC8544_MPIC_REGS_BASE, 1, &irqs, NULL);

    /* Serial */

    if (serial_hds[0])

        serial[0] = serial_mm_init(MPC8544_SERIAL0_REGS_BASE,

                               0, mpic[12+26], 399193,

                        serial_hds[0], 1);

    if (serial_hds[1])

        serial[0] = serial_mm_init(MPC8544_SERIAL1_REGS_BASE,

                        0, mpic[12+26], 399193,

                        serial_hds[0], 1);

    /* PCI */

    pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);

    pci_irqs[0] = mpic[pci_irq_nrs[0]];

    pci_irqs[1] = mpic[pci_irq_nrs[1]];

    pci_irqs[2] = mpic[pci_irq_nrs[2]];

    pci_irqs[3] = mpic[pci_irq_nrs[3]];

    pci_bus = ppce500_pci_init(pci_irqs, MPC8544_PCI_REGS_BASE);

    if (!pci_bus)

        printf("couldn't create PCI controller!\n");

    isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN);

    if (pci_bus) {

        /* Register network interfaces. */

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

            pci_nic_init_nofail(&nd_table[i], "virtio", NULL);

        }

    }

    /* Load kernel. */

    if (kernel_filename) {

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

        if (kernel_size < 0) {

            kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,

                                   NULL, 1, ELF_MACHINE, 0);

            entry = elf_entry;

            loadaddr = elf_lowaddr;

        }

        /* XXX try again as binary */

        if (kernel_size < 0) {

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

                    kernel_filename);

            exit(1);

        }

    }

    /* Load initrd. */

    if (initrd_filename) {

        initrd_size = load_image_targphys(initrd_filename, initrd_base,

                                          ram_size - initrd_base);

        if (initrd_size < 0) {

            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",

                    initrd_filename);

            exit(1);

        }

    }

    /* If we're loading a kernel directly, we must load the device tree too. */

    if (kernel_filename) {

        fdt = mpc8544_load_device_tree(dt_base, ram_size,

                                      initrd_base, initrd_size, kernel_cmdline);

        if (fdt == NULL) {

            fprintf(stderr, "couldn't load device tree\n");

            exit(1);

        }

        cpu_synchronize_state(env);

        /* Set initial guest state. */

        env->gpr[1] = (16<<20) - 8;

        env->gpr[3] = dt_base;

        env->nip = entry;

        /* XXX we currently depend on KVM to create some initial TLB entries. */

    }

    if (kvm_enabled())

        kvmppc_init();

    return;

}


static void test_visitor_out_native_list_bool(TestOutputVisitorData *data,

                                              const void *unused)

{

    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);

}


static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,

                                  int version_id)

{

    VirtIOBlock *s = VIRTIO_BLK(vdev);

    while (qemu_get_sbyte(f)) {

        unsigned nvqs = s->conf.num_queues;

        unsigned vq_idx = 0;

        VirtIOBlockReq *req;

        if (nvqs > 1) {

            vq_idx = qemu_get_be32(f);

            if (vq_idx >= nvqs) {

                error_report("Invalid virtqueue index in request list: %#x",

                             vq_idx);

                return -EINVAL;

            }

        }

        req = qemu_get_virtqueue_element(f, sizeof(VirtIOBlockReq));

        virtio_blk_init_request(s, virtio_get_queue(vdev, vq_idx), req);

        req->next = s->rq;

        s->rq = req;

    }

    return 0;

}


void pci_device_hot_add(Monitor *mon, const QDict *qdict, QObject **ret_data)

{

    PCIDevice *dev = NULL;

    const char *pci_addr = qdict_get_str(qdict, "pci_addr");

    const char *type = qdict_get_str(qdict, "type");

    const char *opts = qdict_get_try_str(qdict, "opts");

    /* strip legacy tag */

    if (!strncmp(pci_addr, "pci_addr=", 9)) {

        pci_addr += 9;

    }

    if (!opts) {

        opts = "";

    }

    if (!strcmp(pci_addr, "auto"))

        pci_addr = NULL;

    if (strcmp(type, "nic") == 0)

        dev = qemu_pci_hot_add_nic(mon, pci_addr, opts);

    else if (strcmp(type, "storage") == 0)

        dev = qemu_pci_hot_add_storage(mon, pci_addr, opts);

    else

        monitor_printf(mon, "invalid type: %s\n", type);

    if (dev) {

        *ret_data =

        qobject_from_jsonf("{ 'domain': 0, 'bus': %d, 'slot': %d, "

                           "'function': %d }", pci_bus_num(dev->bus),

                           PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));

        assert(*ret_data != NULL);

    } else

        monitor_printf(mon, "failed to add %s\n", opts);

}


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

                            int *got_frame_ptr, AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data;

    int buf_size = avpkt->size;

    TTAContext *s = avctx->priv_data;

    int i, ret;

    int cur_chan = 0, framelen = s->frame_length;

    int32_t *p;

    if (avctx->err_recognition & AV_EF_CRCCHECK) {

        if (buf_size < 4 || tta_check_crc(s, buf, buf_size - 4))

            return AVERROR_INVALIDDATA;

    }

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

    // FIXME: seeking

    s->total_frames--;

    if (!s->total_frames && s->last_frame_length)

        framelen = s->last_frame_length;

    /* get output buffer */

    s->frame.nb_samples = framelen;

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

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

        return ret;

    }

    // decode directly to output buffer for 24-bit sample format

    if (s->bps == 3)

        s->decode_buffer = (int32_t *)s->frame.data[0];

    // init per channel states

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

        s->ch_ctx[i].predictor = 0;

        ttafilter_init(&s->ch_ctx[i].filter, ttafilter_configs[s->bps-1]);

        rice_init(&s->ch_ctx[i].rice, 10, 10);

    }

    for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) {

        int32_t *predictor = &s->ch_ctx[cur_chan].predictor;

        TTAFilter *filter = &s->ch_ctx[cur_chan].filter;

        TTARice *rice = &s->ch_ctx[cur_chan].rice;

        uint32_t unary, depth, k;

        int32_t value;

        unary = tta_get_unary(&s->gb);

        if (unary == 0) {

            depth = 0;

            k = rice->k0;

        } else {

            depth = 1;

            k = rice->k1;

            unary--;

        }

        if (get_bits_left(&s->gb) < k) {

            ret = AVERROR_INVALIDDATA;

            goto error;

        }

        if (k) {

            if (k > MIN_CACHE_BITS) {

                ret = AVERROR_INVALIDDATA;

                goto error;

            }

            value = (unary << k) + get_bits(&s->gb, k);

        } else

            value = unary;

        // FIXME: copy paste from original

        switch (depth) {

        case 1:

            rice->sum1 += value - (rice->sum1 >> 4);

            if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1])

                rice->k1--;

            else if(rice->sum1 > shift_16[rice->k1 + 1])

                rice->k1++;

            value += shift_1[rice->k0];

        default:

            rice->sum0 += value - (rice->sum0 >> 4);

            if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0])

                rice->k0--;

            else if(rice->sum0 > shift_16[rice->k0 + 1])

                rice->k0++;

        }

        // extract coded value

        *p = 1 + ((value >> 1) ^ ((value & 1) - 1));

        // run hybrid filter

        ttafilter_process(filter, p);

        // fixed order prediction

#define PRED(x, k) (int32_t)((((uint64_t)x << k) - x) >> k)

        switch (s->bps) {

        case 1: *p += PRED(*predictor, 4); break;

        case 2:

        case 3: *p += PRED(*predictor, 5); break;

        case 4: *p +=      *predictor;     break;

        }

        *predictor = *p;

        // flip channels

        if (cur_chan < (s->channels-1))

            cur_chan++;

        else {

            // decorrelate in case of multiple channels

            if (s->channels > 1) {

                int32_t *r = p - 1;

                for (*p += *r / 2; r > p - s->channels; r--)

                    *r = *(r + 1) - *r;

            }

            cur_chan = 0;

        }

    }

    if (get_bits_left(&s->gb) < 32) {

        ret = AVERROR_INVALIDDATA;

        goto error;

    }

    skip_bits_long(&s->gb, 32); // frame crc

    // convert to output buffer

    if (s->bps == 2) {

        int16_t *samples = (int16_t *)s->frame.data[0];

        for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++)

            *samples++ = *p;

    } else {

        // shift samples for 24-bit sample format

        int32_t *samples = (int32_t *)s->frame.data[0];

        for (i = 0; i < framelen * s->channels; i++)

            *samples++ <<= 8;

        // reset decode buffer

        s->decode_buffer = NULL;

    }

    *got_frame_ptr   = 1;

    *(AVFrame *)data = s->frame;

    return buf_size;

error:

    // reset decode buffer

    if (s->bps == 3)

        s->decode_buffer = NULL;

    return ret;

}


static bool pmsav7_use_background_region(ARMCPU *cpu,

                                         ARMMMUIdx mmu_idx, bool is_user)

{

    /* Return true if we should use the default memory map as a

     * "background" region if there are no hits against any MPU regions.

     */

    CPUARMState *env = &cpu->env;

    if (is_user) {

        return false;

    }

    if (arm_feature(env, ARM_FEATURE_M)) {

        return env->v7m.mpu_ctrl & R_V7M_MPU_CTRL_PRIVDEFENA_MASK;

    } else {

        return regime_sctlr(env, mmu_idx) & SCTLR_BR;

    }

}


static void rtas_system_reboot(sPAPREnvironment *spapr,

                               uint32_t token, uint32_t nargs,

                               target_ulong args,

                               uint32_t nret, target_ulong rets)

{

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

        rtas_st(rets, 0, -3);

        return;

    }

    qemu_system_reset_request();

    rtas_st(rets, 0, 0);

}


static int preallocate(BlockDriverState *bs)

{

    uint64_t nb_sectors;

    uint64_t offset;

    uint64_t host_offset = 0;

    int num;

    int ret;

    QCowL2Meta *meta;

    nb_sectors = bdrv_getlength(bs) >> 9;

    offset = 0;

    while (nb_sectors) {

        num = MIN(nb_sectors, INT_MAX >> 9);

        ret = qcow2_alloc_cluster_offset(bs, offset, &num,

                                         &host_offset, &meta);

        if (ret < 0) {

            return ret;

        }

        ret = qcow2_alloc_cluster_link_l2(bs, meta);

        if (ret < 0) {

            qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters,

                                    QCOW2_DISCARD_NEVER);

            return ret;

        }

        /* There are no dependent requests, but we need to remove our request

         * from the list of in-flight requests */

        if (meta != NULL) {

            QLIST_REMOVE(meta, next_in_flight);

        }

        /* TODO Preallocate data if requested */

        nb_sectors -= num;

        offset += num << 9;

    }

    /*

     * It is expected that the image file is large enough to actually contain

     * all of the allocated clusters (otherwise we get failing reads after

     * EOF). Extend the image to the last allocated sector.

     */

    if (host_offset != 0) {

        uint8_t buf[512];

        memset(buf, 0, 512);

        ret = bdrv_write(bs->file, (host_offset >> 9) + num - 1, buf, 1);

        if (ret < 0) {

            return ret;

        }

    }

    return 0;

}


static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,

                                   MSIMessage *msg, IOHandler *handler)

{

    VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);

    VFIOMSIVector *vector;

    int ret;

    trace_vfio_msix_vector_do_use(vdev->vbasedev.name, nr);

    vector = &vdev->msi_vectors[nr];

    if (!vector->use) {

        vector->vdev = vdev;

        vector->virq = -1;

        if (event_notifier_init(&vector->interrupt, 0)) {

            error_report("vfio: Error: event_notifier_init failed");

        }

        vector->use = true;

        msix_vector_use(pdev, nr);

    }

    qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt),

                        handler, NULL, vector);

    /*

     * Attempt to enable route through KVM irqchip,

     * default to userspace handling if unavailable.

     */

    if (vector->virq >= 0) {

        if (!msg) {

            vfio_remove_kvm_msi_virq(vector);

        } else {

            vfio_update_kvm_msi_virq(vector, *msg);

        }

    } else {

        vfio_add_kvm_msi_virq(vector, msg, true);

    }

    /*

     * We don't want to have the host allocate all possible MSI vectors

     * for a device if they're not in use, so we shutdown and incrementally

     * increase them as needed.

     */

    if (vdev->nr_vectors < nr + 1) {

        vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);

        vdev->nr_vectors = nr + 1;

        ret = vfio_enable_vectors(vdev, true);

        if (ret) {

            error_report("vfio: failed to enable vectors, %d", ret);

        }

    } else {

        int argsz;

        struct vfio_irq_set *irq_set;

        int32_t *pfd;

        argsz = sizeof(*irq_set) + sizeof(*pfd);

        irq_set = g_malloc0(argsz);

        irq_set->argsz = argsz;

        irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |

                         VFIO_IRQ_SET_ACTION_TRIGGER;

        irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;

        irq_set->start = nr;

        irq_set->count = 1;

        pfd = (int32_t *)&irq_set->data;

        if (vector->virq >= 0) {

            *pfd = event_notifier_get_fd(&vector->kvm_interrupt);

        } else {

            *pfd = event_notifier_get_fd(&vector->interrupt);

        }

        ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);

        g_free(irq_set);

        if (ret) {

            error_report("vfio: failed to modify vector, %d", ret);

        }

    }

    return 0;

}


int virtio_load(VirtIODevice *vdev, QEMUFile *f)

{

    int i, ret;

    int32_t config_len;

    uint32_t num;

    uint32_t features;

    uint32_t supported_features;

    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));

    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    if (k->load_config) {

        ret = k->load_config(qbus->parent, f);

        if (ret)

            return ret;

    }

    qemu_get_8s(f, &vdev->status);

    qemu_get_8s(f, &vdev->isr);

    qemu_get_be16s(f, &vdev->queue_sel);

    if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {

        return -1;

    }

    qemu_get_be32s(f, &features);

    if (virtio_set_features(vdev, features) < 0) {

        supported_features = k->get_features(qbus->parent);

        error_report("Features 0x%x unsupported. Allowed features: 0x%x",

                     features, supported_features);

        return -1;

    }

    config_len = qemu_get_be32(f);

    if (config_len != vdev->config_len) {

        error_report("Unexpected config length 0x%x. Expected 0x%zx",

                     config_len, vdev->config_len);

        return -1;

    }

    qemu_get_buffer(f, vdev->config, vdev->config_len);

    num = qemu_get_be32(f);

    if (num > VIRTIO_PCI_QUEUE_MAX) {

        error_report("Invalid number of PCI queues: 0x%x", num);

        return -1;

    }

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

        vdev->vq[i].vring.num = qemu_get_be32(f);

        if (k->has_variable_vring_alignment) {

            vdev->vq[i].vring.align = qemu_get_be32(f);

        }

        vdev->vq[i].pa = qemu_get_be64(f);

        qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);

        vdev->vq[i].signalled_used_valid = false;

        vdev->vq[i].notification = true;

        if (vdev->vq[i].pa) {

            uint16_t nheads;

            virtqueue_init(&vdev->vq[i]);

            nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;

            /* Check it isn't doing very strange things with descriptor numbers. */

            if (nheads > vdev->vq[i].vring.num) {

                error_report("VQ %d size 0x%x Guest index 0x%x "

                             "inconsistent with Host index 0x%x: delta 0x%x",

                             i, vdev->vq[i].vring.num,

                             vring_avail_idx(&vdev->vq[i]),

                             vdev->vq[i].last_avail_idx, nheads);

                return -1;

            }

        } else if (vdev->vq[i].last_avail_idx) {

            error_report("VQ %d address 0x0 "

                         "inconsistent with Host index 0x%x",

                         i, vdev->vq[i].last_avail_idx);

                return -1;

	}

        if (k->load_queue) {

            ret = k->load_queue(qbus->parent, i, f);

            if (ret)

                return ret;

        }

    }

    virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);

    return 0;

}


static int pci_vmsvga_initfn(PCIDevice *dev)

{

    struct pci_vmsvga_state_s *s =

        DO_UPCAST(struct pci_vmsvga_state_s, card, dev);

    pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);

    pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);

    pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA);

    s->card.config[PCI_CACHE_LINE_SIZE]	= 0x08;		/* Cache line size */

    s->card.config[PCI_LATENCY_TIMER] = 0x40;		/* Latency timer */

    s->card.config[PCI_SUBSYSTEM_VENDOR_ID] = PCI_VENDOR_ID_VMWARE & 0xff;

    s->card.config[PCI_SUBSYSTEM_VENDOR_ID + 1]	= PCI_VENDOR_ID_VMWARE >> 8;

    s->card.config[PCI_SUBSYSTEM_ID] = SVGA_PCI_DEVICE_ID & 0xff;

    s->card.config[PCI_SUBSYSTEM_ID + 1] = SVGA_PCI_DEVICE_ID >> 8;

    s->card.config[PCI_INTERRUPT_LINE] = 0xff;		/* End */

    pci_register_bar(&s->card, 0, 0x10,

                    PCI_BASE_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);

    pci_register_bar(&s->card, 1, VGA_RAM_SIZE,

                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_mem);

    pci_register_bar(&s->card, 2, SVGA_FIFO_SIZE,

                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_fifo);

    vmsvga_init(&s->chip, VGA_RAM_SIZE);

    if (!dev->rom_bar) {

        /* compatibility with pc-0.13 and older */

        vga_init_vbe(&s->chip.vga);

    }

    return 0;

}


static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)

{

    QEMUIOVector qiov;

    int noffsets;

    int i, ret;

    struct iovec iov = {

        .iov_base = table->offsets,

        .iov_len = s->header.cluster_size * s->header.table_size,

    };

    qemu_iovec_init_external(&qiov, &iov, 1);

    trace_qed_read_table(s, offset, table);

    ret = bdrv_preadv(s->bs->file, offset, &qiov);

    if (ret < 0) {

        goto out;

    }

    /* Byteswap offsets */

    qed_acquire(s);

    noffsets = qiov.size / sizeof(uint64_t);

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

        table->offsets[i] = le64_to_cpu(table->offsets[i]);

    }

    qed_release(s);

    ret = 0;

out:

    /* Completion */

    trace_qed_read_table_cb(s, table, ret);

    return ret;

}


long do_sigreturn(CPUState *env)

{

        struct target_signal_frame *sf;

        uint32_t up_psr, pc, npc;

        target_sigset_t set;

        sigset_t host_set;

        abi_ulong fpu_save;

        int err, i;

        sf = (struct target_signal_frame *)g2h(env->regwptr[UREG_FP]);

#if 0

	fprintf(stderr, "sigreturn\n");

	fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);

#endif

	//cpu_dump_state(env, stderr, fprintf, 0);

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

#if 0

        if (verify_area (VERIFY_READ, sf, sizeof (*sf)))

                goto segv_and_exit;

#endif

        if (((uint) sf) & 3)

                goto segv_and_exit;

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

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

        if ((pc | npc) & 3)

                goto segv_and_exit;

        /* 2. Restore the state */

        err |= __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;

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

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

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

	}

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

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

	}

        err |= __get_user(fpu_save, (abi_ulong *)&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.

         */

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

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

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

        }

        target_to_host_sigset_internal(&host_set, &set);

        sigprocmask(SIG_SETMASK, &host_set, NULL);

        if (err)

                goto segv_and_exit;

        return env->regwptr[0];

segv_and_exit:

	force_sig(TARGET_SIGSEGV);

}


int cpu_exec(CPUState *cpu)

{

    CPUClass *cc = CPU_GET_CLASS(cpu);

#ifdef TARGET_I386

    X86CPU *x86_cpu = X86_CPU(cpu);

    CPUArchState *env = &x86_cpu->env;

#endif

    int ret, interrupt_request;

    TranslationBlock *tb;

    uint8_t *tc_ptr;

    uintptr_t next_tb;

    SyncClocks sc;

    if (cpu->halted) {

#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)

        if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {

            apic_poll_irq(x86_cpu->apic_state);

            cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);

        }

#endif

        if (!cpu_has_work(cpu)) {

            return EXCP_HALTED;

        }

        cpu->halted = 0;

    }

    current_cpu = cpu;

    atomic_mb_set(&tcg_current_cpu, cpu);

    rcu_read_lock();

    if (unlikely(atomic_mb_read(&exit_request))) {

        cpu->exit_request = 1;

    }

    cc->cpu_exec_enter(cpu);

    /* Calculate difference between guest clock and host clock.

     * This delay includes the delay of the last cycle, so

     * what we have to do is sleep until it is 0. As for the

     * advance/delay we gain here, we try to fix it next time.

     */

    init_delay_params(&sc, cpu);

    /* prepare setjmp context for exception handling */

    for(;;) {

        if (sigsetjmp(cpu->jmp_env, 0) == 0) {

            /* if an exception is pending, we execute it here */

            if (cpu->exception_index >= 0) {

                if (cpu->exception_index >= EXCP_INTERRUPT) {

                    /* exit request from the cpu execution loop */

                    ret = cpu->exception_index;

                    if (ret == EXCP_DEBUG) {

                        cpu_handle_debug_exception(cpu);

                    }

                    cpu->exception_index = -1;

                    break;

                } else {

#if defined(CONFIG_USER_ONLY)

                    /* if user mode only, we simulate a fake exception

                       which will be handled outside the cpu execution

                       loop */

#if defined(TARGET_I386)

                    cc->do_interrupt(cpu);

#endif

                    ret = cpu->exception_index;

                    cpu->exception_index = -1;

                    break;

#else

                    cc->do_interrupt(cpu);

                    cpu->exception_index = -1;

#endif

                }

            }

            next_tb = 0; /* force lookup of first TB */

            for(;;) {

                interrupt_request = cpu->interrupt_request;

                if (unlikely(interrupt_request)) {

                    if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {

                        /* Mask out external interrupts for this step. */

                        interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;

                    }

                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {

                        cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;

                        cpu->exception_index = EXCP_DEBUG;

                        cpu_loop_exit(cpu);

                    }

                    if (interrupt_request & CPU_INTERRUPT_HALT) {

                        cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;

                        cpu->halted = 1;

                        cpu->exception_index = EXCP_HLT;

                        cpu_loop_exit(cpu);

                    }

#if defined(TARGET_I386)

                    if (interrupt_request & CPU_INTERRUPT_INIT) {

                        cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);

                        do_cpu_init(x86_cpu);

                        cpu->exception_index = EXCP_HALTED;

                        cpu_loop_exit(cpu);

                    }

#else

                    if (interrupt_request & CPU_INTERRUPT_RESET) {

                        cpu_reset(cpu);

                    }

#endif

                    /* The target hook has 3 exit conditions:

                       False when the interrupt isn't processed,

                       True when it is, and we should restart on a new TB,

                       and via longjmp via cpu_loop_exit.  */

                    if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {

                        next_tb = 0;

                    }

                    /* Don't use the cached interrupt_request value,

                       do_interrupt may have updated the EXITTB flag. */

                    if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {

                        cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;

                        /* ensure that no TB jump will be modified as

                           the program flow was changed */

                        next_tb = 0;

                    }

                }

                if (unlikely(cpu->exit_request)) {

                    cpu->exit_request = 0;

                    cpu->exception_index = EXCP_INTERRUPT;

                    cpu_loop_exit(cpu);

                }

                tb_lock();

                tb = tb_find_fast(cpu);

                /* Note: we do it here to avoid a gcc bug on Mac OS X when

                   doing it in tb_find_slow */

                if (tcg_ctx.tb_ctx.tb_invalidated_flag) {

                    /* as some TB could have been invalidated because

                       of memory exceptions while generating the code, we

                       must recompute the hash index here */

                    next_tb = 0;

                    tcg_ctx.tb_ctx.tb_invalidated_flag = 0;

                }

                if (qemu_loglevel_mask(CPU_LOG_EXEC)) {

                    qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n",

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

                }

                /* see if we can patch the calling TB. When the TB

                   spans two pages, we cannot safely do a direct

                   jump. */

                if (next_tb != 0 && tb->page_addr[1] == -1

                    && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {

                    tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),

                                next_tb & TB_EXIT_MASK, tb);

                }

                tb_unlock();

                if (likely(!cpu->exit_request)) {

                    trace_exec_tb(tb, tb->pc);

                    tc_ptr = tb->tc_ptr;

                    /* execute the generated code */

                    cpu->current_tb = tb;

                    next_tb = cpu_tb_exec(cpu, tc_ptr);

                    cpu->current_tb = NULL;

                    switch (next_tb & TB_EXIT_MASK) {

                    case TB_EXIT_REQUESTED:

                        /* Something asked us to stop executing

                         * chained TBs; just continue round the main

                         * loop. Whatever requested the exit will also

                         * have set something else (eg exit_request or

                         * interrupt_request) which we will handle

                         * next time around the loop.  But we need to

                         * ensure the tcg_exit_req read in generated code

                         * comes before the next read of cpu->exit_request

                         * or cpu->interrupt_request.

                         */

                        smp_rmb();

                        next_tb = 0;

                        break;

                    case TB_EXIT_ICOUNT_EXPIRED:

                    {

                        /* Instruction counter expired.  */

                        int insns_left = cpu->icount_decr.u32;

                        if (cpu->icount_extra && insns_left >= 0) {

                            /* Refill decrementer and continue execution.  */

                            cpu->icount_extra += insns_left;

                            insns_left = MIN(0xffff, cpu->icount_extra);

                            cpu->icount_extra -= insns_left;

                            cpu->icount_decr.u16.low = insns_left;

                        } else {

                            if (insns_left > 0) {

                                /* Execute remaining instructions.  */

                                tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);

                                cpu_exec_nocache(cpu, insns_left, tb);

                                align_clocks(&sc, cpu);

                            }

                            cpu->exception_index = EXCP_INTERRUPT;

                            next_tb = 0;

                            cpu_loop_exit(cpu);

                        }

                        break;

                    }

                    default:

                        break;

                    }

                }

                /* Try to align the host and virtual clocks

                   if the guest is in advance */

                align_clocks(&sc, cpu);

                /* reset soft MMU for next block (it can currently

                   only be set by a memory fault) */

            } /* for(;;) */

        } else {

            /* Reload env after longjmp - the compiler may have smashed all

             * local variables as longjmp is marked 'noreturn'. */

            cpu = current_cpu;

            cc = CPU_GET_CLASS(cpu);

            cpu->can_do_io = 1;

#ifdef TARGET_I386

            x86_cpu = X86_CPU(cpu);

            env = &x86_cpu->env;

#endif

            tb_lock_reset();

        }

    } /* for(;;) */

    cc->cpu_exec_exit(cpu);

    rcu_read_unlock();

    /* fail safe : never use current_cpu outside cpu_exec() */

    current_cpu = NULL;

    /* Does not need atomic_mb_set because a spurious wakeup is okay.  */

    atomic_set(&tcg_current_cpu, NULL);

    return ret;

}


static int dvbsub_parse_clut_segment(AVCodecContext *avctx,

                                     const uint8_t *buf, int buf_size)

{

    DVBSubContext *ctx = avctx->priv_data;

    const uint8_t *buf_end = buf + buf_size;

    int i, clut_id;

    int version;

    DVBSubCLUT *clut;

    int entry_id, depth , full_range;

    int y, cr, cb, alpha;

    int r, g, b, r_add, g_add, b_add;

    ff_dlog(avctx, "DVB clut packet:\n");

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

        ff_dlog(avctx, "%02x ", buf[i]);

        if (i % 16 == 15)

            ff_dlog(avctx, "\n");

    }

    if (i % 16)

        ff_dlog(avctx, "\n");

    clut_id = *buf++;

    version = ((*buf)>>4)&15;

    buf += 1;

    clut = get_clut(ctx, clut_id);

    if (!clut) {

        clut = av_malloc(sizeof(DVBSubCLUT));

        if (!clut)

            return AVERROR(ENOMEM);

        memcpy(clut, &default_clut, sizeof(DVBSubCLUT));

        clut->id = clut_id;

        clut->version = -1;

        clut->next = ctx->clut_list;

        ctx->clut_list = clut;

    }

    if (clut->version != version) {

    clut->version = version;

    while (buf + 4 < buf_end) {

        entry_id = *buf++;

        depth = (*buf) & 0xe0;

        if (depth == 0) {

            av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf);

            return 0;

        }

        full_range = (*buf++) & 1;

        if (full_range) {

            y = *buf++;

            cr = *buf++;

            cb = *buf++;

            alpha = *buf++;

        } else {

            y = buf[0] & 0xfc;

            cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4;

            cb = (buf[1] << 2) & 0xf0;

            alpha = (buf[1] << 6) & 0xc0;

            buf += 2;

        }

        if (y == 0)

            alpha = 0xff;

        YUV_TO_RGB1_CCIR(cb, cr);

        YUV_TO_RGB2_CCIR(r, g, b, y);

        ff_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha);

        if (!!(depth & 0x80) + !!(depth & 0x40) + !!(depth & 0x20) > 1) {

            ff_dlog(avctx, "More than one bit level marked: %x\n", depth);

            if (avctx->strict_std_compliance > FF_COMPLIANCE_NORMAL)

                return AVERROR_INVALIDDATA;

        }

        if (depth & 0x80)

            clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha);

        else if (depth & 0x40)

            clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha);

        else if (depth & 0x20)

            clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha);

    }

    }

    return 0;

}


static void load_word(DBDMA_channel *ch, int key, uint32_t addr,

                     uint16_t len)

{

    dbdma_cmd *current = &ch->current;

    uint32_t val;

    DBDMA_DPRINTF("load_word\n");

    /* only implements KEY_SYSTEM */

    if (key != KEY_SYSTEM) {

        printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key);

        kill_channel(ch);

        return;

    }

    cpu_physical_memory_read(addr, (uint8_t*)&val, len);

    if (len == 2)

        val = (val << 16) | (current->cmd_dep & 0x0000ffff);

    else if (len == 1)

        val = (val << 24) | (current->cmd_dep & 0x00ffffff);

    current->cmd_dep = val;

    if (conditional_wait(ch))

        goto wait;

    current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS]));

    dbdma_cmdptr_save(ch);

    ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH);

    conditional_interrupt(ch);

    next(ch);

wait:

    qemu_bh_schedule(dbdma_bh);

}


static void nvdimm_dsm_device(NvdimmDsmIn *in, hwaddr dsm_mem_addr)

{

    /* See the comments in nvdimm_dsm_root(). */

    if (!in->function) {

        nvdimm_dsm_function0(0 /* No function supported other than

                                  function 0 */, dsm_mem_addr);

        return;

    }

    /* No function except function 0 is supported yet. */

    nvdimm_dsm_no_payload(1 /* Not Supported */, dsm_mem_addr);

}


static void bdrv_co_em_bh(void *opaque)

{

    BlockAIOCBCoroutine *acb = opaque;

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

    qemu_bh_delete(acb->bh);

    qemu_aio_unref(acb);

}


static int qcow2_change_backing_file(BlockDriverState *bs,

    const char *backing_file, const char *backing_fmt)

{

    /* Backing file format doesn't make sense without a backing file */

    if (backing_fmt && !backing_file) {

        return -EINVAL;

    }

    pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");

    pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");

    return qcow2_update_header(bs);

}


void helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1)

{

    int relation;

    set_float_exception_flags(0, &env->fp_status);

    relation = float64_compare(t0, t1, &env->fp_status);

    if (unlikely(relation == float_relation_unordered)) {

        update_fpscr(env, GETPC());

    } else {

        env->sr_t = (relation == float_relation_equal);

    }

}


int qcow2_update_snapshot_refcount(BlockDriverState *bs,

    int64_t l1_table_offset, int l1_size, int addend)

{

    BDRVQcow2State *s = bs->opaque;

    uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, refcount;

    bool l1_allocated = false;

    int64_t old_offset, old_l2_offset;

    int i, j, l1_modified = 0, nb_csectors;

    int ret;

    assert(addend >= -1 && addend <= 1);

    l2_table = NULL;

    l1_table = NULL;

    l1_size2 = l1_size * sizeof(uint64_t);

    s->cache_discards = true;

    /* WARNING: qcow2_snapshot_goto relies on this function not using the

     * l1_table_offset when it is the current s->l1_table_offset! Be careful

     * when changing this! */

    if (l1_table_offset != s->l1_table_offset) {

        l1_table = g_try_malloc0(align_offset(l1_size2, 512));

        if (l1_size2 && l1_table == NULL) {

            ret = -ENOMEM;

            goto fail;

        }

        l1_allocated = true;

        ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2);

        if (ret < 0) {

            goto fail;

        }

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

            be64_to_cpus(&l1_table[i]);

    } else {

        assert(l1_size == s->l1_size);

        l1_table = s->l1_table;

        l1_allocated = false;

    }

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

        l2_offset = l1_table[i];

        if (l2_offset) {

            old_l2_offset = l2_offset;

            l2_offset &= L1E_OFFSET_MASK;

            if (offset_into_cluster(s, l2_offset)) {

                qcow2_signal_corruption(bs, true, -1, -1, "L2 table offset %#"

                                        PRIx64 " unaligned (L1 index: %#x)",

                                        l2_offset, i);

                ret = -EIO;

                goto fail;

            }

            ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,

                (void**) &l2_table);

            if (ret < 0) {

                goto fail;

            }

            for(j = 0; j < s->l2_size; j++) {

                uint64_t cluster_index;

                offset = be64_to_cpu(l2_table[j]);

                old_offset = offset;

                offset &= ~QCOW_OFLAG_COPIED;

                switch (qcow2_get_cluster_type(offset)) {

                    case QCOW2_CLUSTER_COMPRESSED:

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

                                       s->csize_mask) + 1;

                        if (addend != 0) {

                            ret = update_refcount(bs,

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

                                nb_csectors * 512, abs(addend), addend < 0,

                                QCOW2_DISCARD_SNAPSHOT);

                            if (ret < 0) {

                                goto fail;

                            }

                        }

                        /* compressed clusters are never modified */

                        refcount = 2;

                        break;

                    case QCOW2_CLUSTER_NORMAL:

                    case QCOW2_CLUSTER_ZERO:

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

                            qcow2_signal_corruption(bs, true, -1, -1, "Data "

                                                    "cluster offset %#llx "

                                                    "unaligned (L2 offset: %#"

                                                    PRIx64 ", L2 index: %#x)",

                                                    offset & L2E_OFFSET_MASK,

                                                    l2_offset, j);

                            ret = -EIO;

                            goto fail;

                        }

                        cluster_index = (offset & L2E_OFFSET_MASK) >> s->cluster_bits;

                        if (!cluster_index) {

                            /* unallocated */

                            refcount = 0;

                            break;

                        }

                        if (addend != 0) {

                            ret = qcow2_update_cluster_refcount(bs,

                                    cluster_index, abs(addend), addend < 0,

                                    QCOW2_DISCARD_SNAPSHOT);

                            if (ret < 0) {

                                goto fail;

                            }

                        }

                        ret = qcow2_get_refcount(bs, cluster_index, &refcount);

                        if (ret < 0) {

                            goto fail;

                        }

                        break;

                    case QCOW2_CLUSTER_UNALLOCATED:

                        refcount = 0;

                        break;

                    default:

                        abort();

                }

                if (refcount == 1) {

                    offset |= QCOW_OFLAG_COPIED;

                }

                if (offset != old_offset) {

                    if (addend > 0) {

                        qcow2_cache_set_dependency(bs, s->l2_table_cache,

                            s->refcount_block_cache);

                    }

                    l2_table[j] = cpu_to_be64(offset);

                    qcow2_cache_entry_mark_dirty(bs, s->l2_table_cache,

                                                 l2_table);

                }

            }

            qcow2_cache_put(bs, s->l2_table_cache, (void **) &l2_table);

            if (addend != 0) {

                ret = qcow2_update_cluster_refcount(bs, l2_offset >>

                                                        s->cluster_bits,

                                                    abs(addend), addend < 0,

                                                    QCOW2_DISCARD_SNAPSHOT);

                if (ret < 0) {

                    goto fail;

                }

            }

            ret = qcow2_get_refcount(bs, l2_offset >> s->cluster_bits,

                                     &refcount);

            if (ret < 0) {

                goto fail;

            } else if (refcount == 1) {

                l2_offset |= QCOW_OFLAG_COPIED;

            }

            if (l2_offset != old_l2_offset) {

                l1_table[i] = l2_offset;

                l1_modified = 1;

            }

        }

    }

    ret = bdrv_flush(bs);

fail:

    if (l2_table) {

        qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);

    }

    s->cache_discards = false;

    qcow2_process_discards(bs, ret);

    /* Update L1 only if it isn't deleted anyway (addend = -1) */

    if (ret == 0 && addend >= 0 && l1_modified) {

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

            cpu_to_be64s(&l1_table[i]);

        }

        ret = bdrv_pwrite_sync(bs->file, l1_table_offset,

                               l1_table, l1_size2);

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

            be64_to_cpus(&l1_table[i]);

        }

    }

    if (l1_allocated)

        g_free(l1_table);

    return ret;

}


static int enable_write_target(BDRVVVFATState *s, Error **errp)

{

    BlockDriver *bdrv_qcow = NULL;

    QemuOpts *opts = NULL;

    int ret;

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

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

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

    s->qcow_filename = g_malloc(1024);

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

    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);

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

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

    qemu_opts_del(opts);

    if (ret < 0) {

        goto err;

    }

    s->qcow = NULL;

    ret = bdrv_open(&s->qcow, s->qcow_filename, NULL, NULL,

                    BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH,

                    bdrv_qcow, errp);

    if (ret < 0) {

        goto err;

    }

#ifndef _WIN32

    unlink(s->qcow_filename);

#endif

    bdrv_set_backing_hd(s->bs, bdrv_new());

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

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

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

    return 0;

err:

    g_free(s->qcow_filename);

    s->qcow_filename = NULL;

    return ret;

}


static void dca_init_vlcs(void)

{

    static int vlcs_inited = 0;

    int i, j;

    if (vlcs_inited)

        return;

    dca_bitalloc_index.offset = 1;

    dca_bitalloc_index.wrap = 2;

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

        init_vlc(&dca_bitalloc_index.vlc[i], bitalloc_12_vlc_bits[i], 12,

                 bitalloc_12_bits[i], 1, 1,

                 bitalloc_12_codes[i], 2, 2, 1);

    dca_scalefactor.offset = -64;

    dca_scalefactor.wrap = 2;

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

        init_vlc(&dca_scalefactor.vlc[i], SCALES_VLC_BITS, 129,

                 scales_bits[i], 1, 1,

                 scales_codes[i], 2, 2, 1);

    dca_tmode.offset = 0;

    dca_tmode.wrap = 1;

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

        init_vlc(&dca_tmode.vlc[i], tmode_vlc_bits[i], 4,

                 tmode_bits[i], 1, 1,

                 tmode_codes[i], 2, 2, 1);

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

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

            if(!bitalloc_codes[i][j]) break;

            dca_smpl_bitalloc[i+1].offset = bitalloc_offsets[i];

            dca_smpl_bitalloc[i+1].wrap = 1 + (j > 4);

            init_vlc(&dca_smpl_bitalloc[i+1].vlc[j], bitalloc_maxbits[i][j],

                     bitalloc_sizes[i],

                     bitalloc_bits[i][j], 1, 1,

                     bitalloc_codes[i][j], 2, 2, 1);

        }

    vlcs_inited = 1;

}


static inline int is_yuv_planar(PixFmtInfo *ps)

{

    return (ps->color_type == FF_COLOR_YUV ||

            ps->color_type == FF_COLOR_YUV_JPEG) && !ps->is_packed;

}


AVFilter *avfilter_get_by_name(const char *name)

{

    int i;

    for (i = 0; registered_avfilters[i]; i++)

        if (!strcmp(registered_avfilters[i]->name, name))

            return registered_avfilters[i];

    return NULL;

}


static int output_frame(H264Context *h, AVFrame *dst, AVFrame *src)

{

    int i;

    int ret = av_frame_ref(dst, src);

    if (ret < 0)

        return ret;

    if (!h->sps.crop)

        return 0;

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

        int hshift = (i > 0) ? h->chroma_x_shift : 0;

        int vshift = (i > 0) ? h->chroma_y_shift : 0;

        int off    = ((h->sps.crop_left >> hshift) << h->pixel_shift) +

                     (h->sps.crop_top >> vshift) * dst->linesize[i];

        dst->data[i] += off;

    }

    return 0;

}


static inline void futex_wake(QemuEvent *ev, int n)

{

    if (n == 1) {

        pthread_cond_signal(&ev->cond);

    } else {

        pthread_cond_broadcast(&ev->cond);

    }

}


void vnc_flush(VncState *vs)

{

    if (vs->output.offset)

        vnc_client_write(vs);

}


static void get_private_data(OutputStream *os)

{

    AVCodecContext *codec = os->ctx->streams[0]->codec;

    uint8_t *ptr = codec->extradata;

    int size = codec->extradata_size;

    int i;

    if (codec->codec_id == AV_CODEC_ID_H264) {

        ff_avc_write_annexb_extradata(ptr, &ptr, &size);

        if (!ptr)

            ptr = codec->extradata;

    }

    if (!ptr)

        return;

    os->private_str = av_mallocz(2*size + 1);

    if (!os->private_str)

        return;

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

        snprintf(&os->private_str[2*i], 3, "%02x", ptr[i]);

    if (ptr != codec->extradata)

        av_free(ptr);

}


static int bdrv_qed_open(BlockDriverState *bs, int flags)

{

    BDRVQEDState *s = bs->opaque;

    QEDHeader le_header;

    int64_t file_size;

    int ret;

    s->bs = bs;

    QSIMPLEQ_INIT(&s->allocating_write_reqs);

    ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header));

    if (ret < 0) {

        return ret;

    }

    ret = 0; /* ret should always be 0 or -errno */

    qed_header_le_to_cpu(&le_header, &s->header);

    if (s->header.magic != QED_MAGIC) {

        return -EINVAL;

    }

    if (s->header.features & ~QED_FEATURE_MASK) {

        /* image uses unsupported feature bits */

        char buf[64];

        snprintf(buf, sizeof(buf), "%" PRIx64,

            s->header.features & ~QED_FEATURE_MASK);

        qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,

            bs->device_name, "QED", buf);

        return -ENOTSUP;

    }

    if (!qed_is_cluster_size_valid(s->header.cluster_size)) {

        return -EINVAL;

    }

    /* Round down file size to the last cluster */

    file_size = bdrv_getlength(bs->file);

    if (file_size < 0) {

        return file_size;

    }

    s->file_size = qed_start_of_cluster(s, file_size);

    if (!qed_is_table_size_valid(s->header.table_size)) {

        return -EINVAL;

    }

    if (!qed_is_image_size_valid(s->header.image_size,

                                 s->header.cluster_size,

                                 s->header.table_size)) {

        return -EINVAL;

    }

    if (!qed_check_table_offset(s, s->header.l1_table_offset)) {

        return -EINVAL;

    }

    s->table_nelems = (s->header.cluster_size * s->header.table_size) /

                      sizeof(uint64_t);

    s->l2_shift = ffs(s->header.cluster_size) - 1;

    s->l2_mask = s->table_nelems - 1;

    s->l1_shift = s->l2_shift + ffs(s->table_nelems) - 1;

    if ((s->header.features & QED_F_BACKING_FILE)) {

        if ((uint64_t)s->header.backing_filename_offset +

            s->header.backing_filename_size >

            s->header.cluster_size * s->header.header_size) {

            return -EINVAL;

        }

        ret = qed_read_string(bs->file, s->header.backing_filename_offset,

                              s->header.backing_filename_size, bs->backing_file,

                              sizeof(bs->backing_file));

        if (ret < 0) {

            return ret;

        }

        if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {

            pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");

        }

    }

    /* Reset unknown autoclear feature bits.  This is a backwards

     * compatibility mechanism that allows images to be opened by older

     * programs, which "knock out" unknown feature bits.  When an image is

     * opened by a newer program again it can detect that the autoclear

     * feature is no longer valid.

     */

    if ((s->header.autoclear_features & ~QED_AUTOCLEAR_FEATURE_MASK) != 0 &&

        !bdrv_is_read_only(bs->file)) {

        s->header.autoclear_features &= QED_AUTOCLEAR_FEATURE_MASK;

        ret = qed_write_header_sync(s);

        if (ret) {

            return ret;

        }

        /* From here on only known autoclear feature bits are valid */

        bdrv_flush(bs->file);

    }

    s->l1_table = qed_alloc_table(s);

    qed_init_l2_cache(&s->l2_cache);

    ret = qed_read_l1_table_sync(s);

    if (ret) {

        goto out;

    }

    /* If image was not closed cleanly, check consistency */

    if (s->header.features & QED_F_NEED_CHECK) {

        /* Read-only images cannot be fixed.  There is no risk of corruption

         * since write operations are not possible.  Therefore, allow

         * potentially inconsistent images to be opened read-only.  This can

         * aid data recovery from an otherwise inconsistent image.

         */

        if (!bdrv_is_read_only(bs->file)) {

            BdrvCheckResult result = {0};

            ret = qed_check(s, &result, true);

            if (!ret && !result.corruptions && !result.check_errors) {

                /* Ensure fixes reach storage before clearing check bit */

                bdrv_flush(s->bs);

                s->header.features &= ~QED_F_NEED_CHECK;

                qed_write_header_sync(s);

            }

        }

    }

out:

    if (ret) {

        qed_free_l2_cache(&s->l2_cache);

        qemu_vfree(s->l1_table);

    }

    return ret;

}


static void do_key_event(VncState *vs, int down, int keycode, int sym)
{
    /* QEMU console switch */
    switch(keycode) {
    case 0x2a:                          /* Left Shift */
    case 0x36:                          /* Right Shift */
    case 0x1d:                          /* Left CTRL */
    case 0x9d:                          /* Right CTRL */
    case 0x38:                          /* Left ALT */
    case 0xb8:                          /* Right ALT */
        if (down)
            vs->modifiers_state[keycode] = 1;
        else
            vs->modifiers_state[keycode] = 0;
        break;
    case 0x02 ... 0x0a: /* '1' to '9' keys */
        if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
            /* Reset the modifiers sent to the current console */
            reset_keys(vs);
            console_select(keycode - 0x02);
            return;
        break;
    case 0x3a:                        /* CapsLock */
    case 0x45:                        /* NumLock */
        if (!down)
            vs->modifiers_state[keycode] ^= 1;
        break;
    if (keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
        /* If the numlock state needs to change then simulate an additional
           toggles numlock away from the VNC window.
        if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
            if (!vs->modifiers_state[0x45]) {
                vs->modifiers_state[0x45] = 1;
                press_key(vs, 0xff7f);
            if (vs->modifiers_state[0x45]) {
                vs->modifiers_state[0x45] = 0;
                press_key(vs, 0xff7f);
    if (is_graphic_console()) {
        if (keycode & 0x80)
            kbd_put_keycode(0xe0);
        if (down)
            kbd_put_keycode(keycode & 0x7f);
        else
            kbd_put_keycode(keycode | 0x80);
        /* QEMU console emulation */
        if (down) {
            int numlock = vs->modifiers_state[0x45];
            switch (keycode) {
            case 0x2a:                          /* Left Shift */
            case 0x36:                          /* Right Shift */
            case 0x1d:                          /* Left CTRL */
            case 0x9d:                          /* Right CTRL */
            case 0x38:                          /* Left ALT */
            case 0xb8:                          /* Right ALT */
                break;
            case 0xc8:
                kbd_put_keysym(QEMU_KEY_UP);
                break;
            case 0xd0:
                kbd_put_keysym(QEMU_KEY_DOWN);
                break;
            case 0xcb:
                kbd_put_keysym(QEMU_KEY_LEFT);
                break;
            case 0xcd:
                kbd_put_keysym(QEMU_KEY_RIGHT);
                break;
            case 0xd3:
                kbd_put_keysym(QEMU_KEY_DELETE);
                break;
            case 0xc7:
                kbd_put_keysym(QEMU_KEY_HOME);
                break;
            case 0xcf:
                kbd_put_keysym(QEMU_KEY_END);
                break;
            case 0xc9:
                kbd_put_keysym(QEMU_KEY_PAGEUP);
                break;
            case 0xd1:
                kbd_put_keysym(QEMU_KEY_PAGEDOWN);
                break;
            case 0x47:
                kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
                break;
            case 0x48:
                kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
                break;
            case 0x49:
                kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
                break;
            case 0x4b:
                kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
                break;
            case 0x4c:
                kbd_put_keysym('5');
                break;
            case 0x4d:
                kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
                break;
            case 0x4f:
                kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
                break;
            case 0x50:
                kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
                break;
            case 0x51:
                kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
                break;
            case 0x52:
                kbd_put_keysym('0');
                break;
            case 0x53:
                kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
                break;
            case 0xb5:
                kbd_put_keysym('/');
                break;
            case 0x37:
                kbd_put_keysym('*');
                break;
            case 0x4a:
                kbd_put_keysym('-');
                break;
            case 0x4e:
                kbd_put_keysym('+');
                break;
            case 0x9c:
                kbd_put_keysym('\n');
                break;
            default:
                kbd_put_keysym(sym);
                break;


void set_link_completion(ReadLineState *rs, int nb_args, const char *str)

{

    size_t len;

    len = strlen(str);

    readline_set_completion_index(rs, len);

    if (nb_args == 2) {

        NetClientState *ncs[MAX_QUEUE_NUM];

        int count, i;

        count = qemu_find_net_clients_except(NULL, ncs,

                                             NET_CLIENT_OPTIONS_KIND_NONE,

                                             MAX_QUEUE_NUM);

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

            const char *name = ncs[i]->name;

            if (!strncmp(str, name, len)) {

                readline_add_completion(rs, name);

            }

        }

    } else if (nb_args == 3) {

        add_completion_option(rs, str, "on");

        add_completion_option(rs, str, "off");

    }

}


static void bufp_alloc(USBRedirDevice *dev, uint8_t *data, uint16_t len,

    uint8_t status, uint8_t ep, void *free_on_destroy)

{

    struct buf_packet *bufp;

    if (!dev->endpoint[EP2I(ep)].bufpq_dropping_packets &&

        dev->endpoint[EP2I(ep)].bufpq_size >

            2 * dev->endpoint[EP2I(ep)].bufpq_target_size) {

        DPRINTF("bufpq overflow, dropping packets ep %02X\n", ep);

        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 1;

    }

    /* Since we're interupting the stream anyways, drop enough packets to get

       back to our target buffer size */

    if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) {

        if (dev->endpoint[EP2I(ep)].bufpq_size >

                dev->endpoint[EP2I(ep)].bufpq_target_size) {

            free(data);

            return;

        }

        dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;

    }

    bufp = g_new(struct buf_packet, 1);

    bufp->data   = data;

    bufp->len    = len;

    bufp->offset = 0;

    bufp->status = status;

    bufp->free_on_destroy = free_on_destroy;

    QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);

    dev->endpoint[EP2I(ep)].bufpq_size++;

}


static inline void check_hwrena(CPUMIPSState *env, int reg)

{

    if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) {

        return;

    }

    do_raise_exception(env, EXCP_RI, GETPC());

}


static bool xen_host_pci_dev_is_virtfn(XenHostPCIDevice *d)

{

    char path[PATH_MAX];

    struct stat buf;

    if (xen_host_pci_sysfs_path(d, "physfn", path, sizeof (path))) {

        return false;

    }

    return !stat(path, &buf);

}


static gboolean guest_exec_output_watch(GIOChannel *ch,

        GIOCondition cond, gpointer p_)

{

    GuestExecIOData *p = (GuestExecIOData *)p_;

    gsize bytes_read;

    GIOStatus gstatus;

    if (cond == G_IO_HUP || cond == G_IO_ERR) {

        goto close;

    }

    if (p->size == p->length) {

        gpointer t = NULL;

        if (!p->truncated && p->size < GUEST_EXEC_MAX_OUTPUT) {

            t = g_try_realloc(p->data, p->size + GUEST_EXEC_IO_SIZE);

        }

        if (t == NULL) {

            /* ignore truncated output */

            gchar buf[GUEST_EXEC_IO_SIZE];

            p->truncated = true;

            gstatus = g_io_channel_read_chars(ch, buf, sizeof(buf),

                                              &bytes_read, NULL);

            if (gstatus == G_IO_STATUS_EOF || gstatus == G_IO_STATUS_ERROR) {

                goto close;

            }

            return true;

        }

        p->size += GUEST_EXEC_IO_SIZE;

        p->data = t;

    }

    /* Calling read API once.

     * On next available data our callback will be called again */

    gstatus = g_io_channel_read_chars(ch, (gchar *)p->data + p->length,

            p->size - p->length, &bytes_read, NULL);

    if (gstatus == G_IO_STATUS_EOF || gstatus == G_IO_STATUS_ERROR) {

        goto close;

    }

    p->length += bytes_read;

    return true;

close:

    g_io_channel_unref(ch);

    g_atomic_int_set(&p->closed, 1);

    return false;

}


static int hq_decode_block(HQContext *c, GetBitContext *gb, int16_t block[64],

                           int qsel, int is_chroma, int is_hqa)

{

    const int32_t *q;

    int val, pos = 1;

    memset(block, 0, 64 * sizeof(*block));

    if (!is_hqa) {

        block[0] = get_sbits(gb, 9) << 6;

        q = ff_hq_quants[qsel][is_chroma][get_bits(gb, 2)];

    } else {

        q = ff_hq_quants[qsel][is_chroma][get_bits(gb, 2)];

        block[0] = get_sbits(gb, 9) << 6;

    }

    for (;;) {

        val  = get_vlc2(gb, c->hq_ac_vlc.table, 9, 2);

        pos += ff_hq_ac_skips[val];

        if (pos >= 64)

            break;

        block[ff_zigzag_direct[pos]] = (ff_hq_ac_syms[val] * q[pos]) >> 12;

        pos++;

    }

    return 0;

}


static void final(const short *i1, const short *i2,

                  void *out, int *statbuf, int len)

{

    int x, i;

    unsigned short int work[50];

    short *ptr = work;

    memcpy(work, statbuf,20);

    memcpy(work + 10, i2, len * 2);

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

        int sum = 0;

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

            sum += i1[9-x] * ptr[x];

        sum >>= 12;

        if (ptr[10] - sum < -32768 || ptr[10] - sum > 32767) {

            memset(out, 0, len * 2);

            memset(statbuf, 0, 20);

            return;

        }

        ptr[10] -= sum;

        ptr++;

    }

    memcpy(out, work+10, len * 2);

    memcpy(statbuf, work + 40, 20);

}


static int showspectrumpic_request_frame(AVFilterLink *outlink)

{

    AVFilterContext *ctx = outlink->src;

    ShowSpectrumContext *s = ctx->priv;

    AVFilterLink *inlink = ctx->inputs[0];

    int ret;

    ret = ff_request_frame(inlink);

    if (ret == AVERROR_EOF && s->outpicref) {

        int samples = av_audio_fifo_size(s->fifo);

        int consumed = 0;

        int y, x = 0, sz = s->orientation == VERTICAL ? s->w : s->h;

        int ch, spf, spb;

        AVFrame *fin;

        spf = s->win_size * (samples / ((s->win_size * sz) * ceil(samples / (float)(s->win_size * sz))));

        spb = (samples / (spf * sz)) * spf;

        fin = ff_get_audio_buffer(inlink, s->win_size);

        if (!fin)

            return AVERROR(ENOMEM);

        while (x < sz) {

            ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size);

            if (ret < 0) {

                av_frame_free(&fin);

                return ret;

            }

            av_audio_fifo_drain(s->fifo, spf);

            if (ret < s->win_size) {

                for (ch = 0; ch < s->nb_display_channels; ch++) {

                    memset(fin->extended_data[ch] + ret * sizeof(float), 0,

                           (s->win_size - ret) * sizeof(float));

                }

            }

            ctx->internal->execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels);

            acalc_magnitudes(s);

            consumed += spf;

            if (consumed >= spb) {

                int h = s->orientation == VERTICAL ? s->h : s->w;

                scale_magnitudes(s, 1. / (consumed / spf));

                plot_spectrum_column(inlink, fin);

                consumed = 0;

                x++;

                for (ch = 0; ch < s->nb_display_channels; ch++)

                    memset(s->magnitudes[ch], 0, h * sizeof(float));

            }

        }

        av_frame_free(&fin);

        s->outpicref->pts = 0;

        if (s->legend) {

            int multi = (s->mode == SEPARATE && s->color_mode == CHANNEL);

            float spp = samples / (float)sz;

            uint8_t *dst;

            drawtext(s->outpicref, 2, outlink->h - 10, "CREATED BY LIBAVFILTER", 0);

            dst = s->outpicref->data[0] + (s->start_y - 1) * s->outpicref->linesize[0] + s->start_x - 1;

            for (x = 0; x < s->w + 1; x++)

                dst[x] = 200;

            dst = s->outpicref->data[0] + (s->start_y + s->h) * s->outpicref->linesize[0] + s->start_x - 1;

            for (x = 0; x < s->w + 1; x++)

                dst[x] = 200;

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

                dst = s->outpicref->data[0] + (y + s->start_y - 1) * s->outpicref->linesize[0];

                dst[s->start_x - 1] = 200;

                dst[s->start_x + s->w] = 200;

            }

            if (s->orientation == VERTICAL) {

                int h = s->mode == SEPARATE ? s->h / s->nb_display_channels : s->h;

                for (ch = 0; ch < (s->mode == SEPARATE ? s->nb_display_channels : 1); ch++) {

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

                        dst = s->outpicref->data[0] + (s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[0];

                        dst[s->start_x - 2] = 200;

                        dst[s->start_x + s->w + 1] = 200;

                    }

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

                        dst = s->outpicref->data[0] + (s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[0];

                        dst[s->start_x - 3] = 200;

                        dst[s->start_x + s->w + 2] = 200;

                    }

                    dst = s->outpicref->data[0] + (s->start_y - 2) * s->outpicref->linesize[0] + s->start_x;

                    for (x = 0; x < s->w; x+=40)

                        dst[x] = 200;

                    dst = s->outpicref->data[0] + (s->start_y - 3) * s->outpicref->linesize[0] + s->start_x;

                    for (x = 0; x < s->w; x+=80)

                        dst[x] = 200;

                    dst = s->outpicref->data[0] + (s->h + s->start_y + 1) * s->outpicref->linesize[0] + s->start_x;

                    for (x = 0; x < s->w; x+=40) {

                        dst[x] = 200;

                    }

                    dst = s->outpicref->data[0] + (s->h + s->start_y + 2) * s->outpicref->linesize[0] + s->start_x;

                    for (x = 0; x < s->w; x+=80) {

                        dst[x] = 200;

                    }

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

                        float hertz = y * (inlink->sample_rate / 2) / (float)(1 << (int)ceil(log2(h)));

                        char *units;

                        if (hertz == 0)

                            units = av_asprintf("DC");

                        else

                            units = av_asprintf("%.2f", hertz);

                        if (!units)

                            return AVERROR(ENOMEM);

                        drawtext(s->outpicref, s->start_x - 8 * strlen(units) - 4, h * (ch + 1) + s->start_y - y - 4, units, 0);

                        av_free(units);

                    }

                }

                for (x = 0; x < s->w; x+=80) {

                    float seconds = x * spp / inlink->sample_rate;

                    char *units;

                    if (x == 0)

                        units = av_asprintf("0");

                    else if (log10(seconds) > 6)

                        units = av_asprintf("%.2fh", seconds / (60 * 60));

                    else if (log10(seconds) > 3)

                        units = av_asprintf("%.2fm", seconds / 60);

                    else

                        units = av_asprintf("%.2fs", seconds);

                    if (!units)

                        return AVERROR(ENOMEM);

                    drawtext(s->outpicref, s->start_x + x - 4 * strlen(units), s->h + s->start_y + 6, units, 0);

                    drawtext(s->outpicref, s->start_x + x - 4 * strlen(units), s->start_y - 12, units, 0);

                    av_free(units);

                }

                drawtext(s->outpicref, outlink->w / 2 - 4 * 4, outlink->h - s->start_y / 2, "TIME", 0);

                drawtext(s->outpicref, s->start_x / 7, outlink->h / 2 - 14 * 4, "FREQUENCY (Hz)", 1);

            } else {

                int w = s->mode == SEPARATE ? s->w / s->nb_display_channels : s->w;

                for (y = 0; y < s->h; y += 20) {

                    dst = s->outpicref->data[0] + (s->start_y + y) * s->outpicref->linesize[0];

                    dst[s->start_x - 2] = 200;

                    dst[s->start_x + s->w + 1] = 200;

                }

                for (y = 0; y < s->h; y += 40) {

                    dst = s->outpicref->data[0] + (s->start_y + y) * s->outpicref->linesize[0];

                    dst[s->start_x - 3] = 200;

                    dst[s->start_x + s->w + 2] = 200;

                }

                for (ch = 0; ch < (s->mode == SEPARATE ? s->nb_display_channels : 1); ch++) {

                    dst = s->outpicref->data[0] + (s->start_y - 2) * s->outpicref->linesize[0] + s->start_x + w * ch;

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

                        dst[x] = 200;

                    dst = s->outpicref->data[0] + (s->start_y - 3) * s->outpicref->linesize[0] + s->start_x + w * ch;

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

                        dst[x] = 200;

                    dst = s->outpicref->data[0] + (s->h + s->start_y + 1) * s->outpicref->linesize[0] + s->start_x + w * ch;

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

                        dst[x] = 200;

                    }

                    dst = s->outpicref->data[0] + (s->h + s->start_y + 2) * s->outpicref->linesize[0] + s->start_x + w * ch;

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

                        dst[x] = 200;

                    }

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

                        float hertz = x * (inlink->sample_rate / 2) / (float)(1 << (int)ceil(log2(w)));

                        char *units;

                        if (hertz == 0)

                            units = av_asprintf("DC");

                        else

                            units = av_asprintf("%.2f", hertz);

                        if (!units)

                            return AVERROR(ENOMEM);

                        drawtext(s->outpicref, s->start_x - 4 * strlen(units) + x + w * ch, s->start_y - 12, units, 0);

                        drawtext(s->outpicref, s->start_x - 4 * strlen(units) + x + w * ch, s->h + s->start_y + 6, units, 0);

                        av_free(units);

                    }

                }

                for (y = 0; y < s->h; y+=40) {

                    float seconds = y * spp / inlink->sample_rate;

                    char *units;

                    if (x == 0)

                        units = av_asprintf("0");

                    else if (log10(seconds) > 6)

                        units = av_asprintf("%.2fh", seconds / (60 * 60));

                    else if (log10(seconds) > 3)

                        units = av_asprintf("%.2fm", seconds / 60);

                    else

                        units = av_asprintf("%.2fs", seconds);

                    if (!units)

                        return AVERROR(ENOMEM);

                    drawtext(s->outpicref, s->start_x - 8 * strlen(units) - 4, s->start_y + y - 4, units, 0);

                    av_free(units);

                }

                drawtext(s->outpicref, s->start_x / 7, outlink->h / 2 - 4 * 4, "TIME", 1);

                drawtext(s->outpicref, outlink->w / 2 - 14 * 4, outlink->h - s->start_y / 2, "FREQUENCY (Hz)", 0);

            }

            for (ch = 0; ch < (multi ? s->nb_display_channels : 1); ch++) {

                int h = multi ? s->h / s->nb_display_channels : s->h;

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

                    float out[3] = { 0., 127.5, 127.5};

                    int chn;

                    for (chn = 0; chn < (s->mode == SEPARATE ? 1 : s->nb_display_channels); chn++) {

                        float yf, uf, vf;

                        int channel = (multi) ? s->nb_display_channels - ch - 1 : chn;

                        float lout[3];

                        color_range(s, channel, &yf, &uf, &vf);

                        pick_color(s, yf, uf, vf, y / (float)h, lout);

                        out[0] += lout[0];

                        out[1] += lout[1];

                        out[2] += lout[2];

                    }

                    memset(s->outpicref->data[0]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[0] + s->w + s->start_x + 20, av_clip_uint8(out[0]), 10);

                    memset(s->outpicref->data[1]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[1] + s->w + s->start_x + 20, av_clip_uint8(out[1]), 10);

                    memset(s->outpicref->data[2]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[2] + s->w + s->start_x + 20, av_clip_uint8(out[2]), 10);

                }

                for (y = 0; ch == 0 && y < h; y += h / 10) {

                    float value = 120.0 * log10(1. - y / (float)h);

                    char *text;

                    if (value < -120)

                        break;

                    text = av_asprintf("%.0f dB", value);

                    if (!text)

                        continue;

                    drawtext(s->outpicref, s->w + s->start_x + 35, s->start_y + y - 5, text, 0);

                    av_free(text);

                }

            }

        }

        ret = ff_filter_frame(outlink, s->outpicref);

        s->outpicref = NULL;

    }

    return ret;

}


static int usb_msd_initfn_storage(USBDevice *dev)

{

    MSDState *s = DO_UPCAST(MSDState, dev, dev);

    BlockDriverState *bs = s->conf.bs;

    SCSIDevice *scsi_dev;

    Error *err = NULL;

    if (!bs) {

        error_report("drive property not set");

        return -1;

    }

    blkconf_serial(&s->conf, &dev->serial);

    /*

     * Hack alert: this pretends to be a block device, but it's really

     * a SCSI bus that can serve only a single device, which it

     * creates automatically.  But first it needs to detach from its

     * blockdev, or else scsi_bus_legacy_add_drive() dies when it

     * attaches again.

     *

     * The hack is probably a bad idea.

     */

    bdrv_detach_dev(bs, &s->dev.qdev);

    s->conf.bs = NULL;

    usb_desc_create_serial(dev);

    usb_desc_init(dev);

    scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),

                 &usb_msd_scsi_info_storage, NULL);

    scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,

                                         s->conf.bootindex, dev->serial,

                                         &err);

    if (!scsi_dev) {

        return -1;

    }

    s->bus.qbus.allow_hotplug = 0;

    usb_msd_handle_reset(dev);

    if (bdrv_key_required(bs)) {

        if (cur_mon) {

            monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s);

            s->dev.auto_attach = 0;

        } else {

            autostart = 0;

        }

    }

    return 0;

}


static gnutls_anon_server_credentials_t vnc_tls_initialize_anon_cred(void)

{

    gnutls_anon_server_credentials_t anon_cred;

    int ret;

    if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {

        VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));

        return NULL;

    }

    gnutls_anon_set_server_dh_params(anon_cred, dh_params);

    return anon_cred;

}


static void hypercall_init(void)
{
    /* hcall-pft */
    spapr_register_hypercall(H_ENTER, h_enter);
    spapr_register_hypercall(H_REMOVE, h_remove);
    spapr_register_hypercall(H_PROTECT, h_protect);
    /* qemu/KVM-PPC specific hcalls */
    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
}


static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)

{

    int64_t total_sectors = bmds->total_sectors;

    int64_t cur_sector = bmds->cur_sector;

    BlockDriverState *bs = bmds->bs;

    BlkMigBlock *blk;

    int nr_sectors;

    if (bmds->shared_base) {

        qemu_mutex_lock_iothread();

        while (cur_sector < total_sectors &&

               !bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,

                                  &nr_sectors)) {

            cur_sector += nr_sectors;

        }

        qemu_mutex_unlock_iothread();

    }

    if (cur_sector >= total_sectors) {

        bmds->cur_sector = bmds->completed_sectors = total_sectors;

        return 1;

    }

    bmds->completed_sectors = cur_sector;

    cur_sector &= ~((int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK - 1);

    /* we are going to transfer a full block even if it is not allocated */

    nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;

    if (total_sectors - cur_sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {

        nr_sectors = total_sectors - cur_sector;

    }

    blk = g_malloc(sizeof(BlkMigBlock));

    blk->buf = g_malloc(BLOCK_SIZE);

    blk->bmds = bmds;

    blk->sector = cur_sector;

    blk->nr_sectors = nr_sectors;

    blk->iov.iov_base = blk->buf;

    blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;

    qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);

    blk_mig_lock();

    block_mig_state.submitted++;

    blk_mig_unlock();

    qemu_mutex_lock_iothread();

    blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,

                                nr_sectors, blk_mig_read_cb, blk);

    bdrv_reset_dirty(bs, cur_sector, nr_sectors);

    qemu_mutex_unlock_iothread();

    bmds->cur_sector = cur_sector + nr_sectors;

    return (bmds->cur_sector >= total_sectors);

}


static int make_setup_request(AVFormatContext *s, const char *host, int port,

                              int lower_transport, const char *real_challenge)

{

    RTSPState *rt = s->priv_data;

    int rtx, j, i, err, interleave = 0;

    RTSPStream *rtsp_st;

    RTSPMessageHeader reply1, *reply = &reply1;

    char cmd[2048];

    const char *trans_pref;

    if (rt->transport == RTSP_TRANSPORT_RDT)

        trans_pref = "x-pn-tng";

    else

        trans_pref = "RTP/AVP";

    /* default timeout: 1 minute */

    rt->timeout = 60;

    /* for each stream, make the setup request */

    /* XXX: we assume the same server is used for the control of each

     * RTSP stream */

    for (j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {

        char transport[2048];

        /**

         * WMS serves all UDP data over a single connection, the RTX, which

         * isn't necessarily the first in the SDP but has to be the first

         * to be set up, else the second/third SETUP will fail with a 461.

         */

        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&

             rt->server_type == RTSP_SERVER_WMS) {

            if (i == 0) {

                /* rtx first */

                for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {

                    int len = strlen(rt->rtsp_streams[rtx]->control_url);

                    if (len >= 4 &&

                        !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,

                                "/rtx"))

                        break;

                }

                if (rtx == rt->nb_rtsp_streams)

                    return -1; /* no RTX found */

                rtsp_st = rt->rtsp_streams[rtx];

            } else

                rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];

        } else

            rtsp_st = rt->rtsp_streams[i];

        /* RTP/UDP */

        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) {

            char buf[256];

            if (rt->server_type == RTSP_SERVER_WMS && i > 1) {

                port = reply->transports[0].client_port_min;

                goto have_port;

            }

            /* first try in specified port range */

            if (RTSP_RTP_PORT_MIN != 0) {

                while (j <= RTSP_RTP_PORT_MAX) {

                    ff_url_join(buf, sizeof(buf), "rtp", NULL, host, -1,

                                "?localport=%d", j);

                    /* we will use two ports per rtp stream (rtp and rtcp) */

                    j += 2;

                    if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0)

                        goto rtp_opened;

                }

            }

#if 0

            /* then try on any port */

            if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {

                err = AVERROR_INVALIDDATA;

                goto fail;

            }

#endif

        rtp_opened:

            port = rtp_get_local_rtp_port(rtsp_st->rtp_handle);

        have_port:

            snprintf(transport, sizeof(transport) - 1,

                     "%s/UDP;", trans_pref);

            if (rt->server_type != RTSP_SERVER_REAL)

                av_strlcat(transport, "unicast;", sizeof(transport));

            av_strlcatf(transport, sizeof(transport),

                     "client_port=%d", port);

            if (rt->transport == RTSP_TRANSPORT_RTP &&

                !(rt->server_type == RTSP_SERVER_WMS && i > 0))

                av_strlcatf(transport, sizeof(transport), "-%d", port + 1);

        }

        /* RTP/TCP */

        else if (lower_transport == RTSP_LOWER_TRANSPORT_TCP) {

            /** For WMS streams, the application streams are only used for

             * UDP. When trying to set it up for TCP streams, the server

             * will return an error. Therefore, we skip those streams. */

            if (rt->server_type == RTSP_SERVER_WMS &&

                s->streams[rtsp_st->stream_index]->codec->codec_type ==

                    AVMEDIA_TYPE_DATA)

                continue;

            snprintf(transport, sizeof(transport) - 1,

                     "%s/TCP;", trans_pref);

            if (rt->server_type == RTSP_SERVER_WMS)

                av_strlcat(transport, "unicast;", sizeof(transport));

            av_strlcatf(transport, sizeof(transport),

                        "interleaved=%d-%d",

                        interleave, interleave + 1);

            interleave += 2;

        }

        else if (lower_transport == RTSP_LOWER_TRANSPORT_UDP_MULTICAST) {

            snprintf(transport, sizeof(transport) - 1,

                     "%s/UDP;multicast", trans_pref);

        }

        if (s->oformat) {

            av_strlcat(transport, ";mode=receive", sizeof(transport));

        } else if (rt->server_type == RTSP_SERVER_REAL ||

                   rt->server_type == RTSP_SERVER_WMS)

            av_strlcat(transport, ";mode=play", sizeof(transport));

        snprintf(cmd, sizeof(cmd),

                 "Transport: %s\r\n",

                 transport);

        if (i == 0 && rt->server_type == RTSP_SERVER_REAL && CONFIG_RTPDEC) {

            char real_res[41], real_csum[9];

            ff_rdt_calc_response_and_checksum(real_res, real_csum,

                                              real_challenge);

            av_strlcatf(cmd, sizeof(cmd),

                        "If-Match: %s\r\n"

                        "RealChallenge2: %s, sd=%s\r\n",

                        rt->session_id, real_res, real_csum);

        }

        ff_rtsp_send_cmd(s, "SETUP", rtsp_st->control_url, cmd, reply, NULL);

        if (reply->status_code == 461 /* Unsupported protocol */ && i == 0) {

            err = 1;

            goto fail;

        } else if (reply->status_code != RTSP_STATUS_OK ||

                   reply->nb_transports != 1) {

            err = AVERROR_INVALIDDATA;

            goto fail;

        }

        /* XXX: same protocol for all streams is required */

        if (i > 0) {

            if (reply->transports[0].lower_transport != rt->lower_transport ||

                reply->transports[0].transport != rt->transport) {

                err = AVERROR_INVALIDDATA;

                goto fail;

            }

        } else {

            rt->lower_transport = reply->transports[0].lower_transport;

            rt->transport = reply->transports[0].transport;

        }

        /* close RTP connection if not chosen */

        if (reply->transports[0].lower_transport != RTSP_LOWER_TRANSPORT_UDP &&

            (lower_transport == RTSP_LOWER_TRANSPORT_UDP)) {

            url_close(rtsp_st->rtp_handle);

            rtsp_st->rtp_handle = NULL;

        }

        switch(reply->transports[0].lower_transport) {

        case RTSP_LOWER_TRANSPORT_TCP:

            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;

            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;

            break;

        case RTSP_LOWER_TRANSPORT_UDP: {

            char url[1024];

            /* Use source address if specified */

            if (reply->transports[0].source[0]) {

                ff_url_join(url, sizeof(url), "rtp", NULL,

                            reply->transports[0].source,

                            reply->transports[0].server_port_min, NULL);

            } else {

                ff_url_join(url, sizeof(url), "rtp", NULL, host,

                            reply->transports[0].server_port_min, NULL);

            }

            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) &&

                rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) {

                err = AVERROR_INVALIDDATA;

                goto fail;

            }

            /* Try to initialize the connection state in a

             * potential NAT router by sending dummy packets.

             * RTP/RTCP dummy packets are used for RDT, too.

             */

            if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && s->iformat &&

                CONFIG_RTPDEC)

                rtp_send_punch_packets(rtsp_st->rtp_handle);

            break;

        }

        case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: {

            char url[1024], namebuf[50];

            struct sockaddr_storage addr;

            int port, ttl;

            if (reply->transports[0].destination.ss_family) {

                addr      = reply->transports[0].destination;

                port      = reply->transports[0].port_min;

                ttl       = reply->transports[0].ttl;

            } else {

                addr      = rtsp_st->sdp_ip;

                port      = rtsp_st->sdp_port;

                ttl       = rtsp_st->sdp_ttl;

            }

            getnameinfo((struct sockaddr*) &addr, sizeof(addr),

                        namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);

            ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,

                        port, "?ttl=%d", ttl);

            if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) {

                err = AVERROR_INVALIDDATA;

                goto fail;

            }

            break;

        }

        }

        if ((err = rtsp_open_transport_ctx(s, rtsp_st)))

            goto fail;

    }

    if (reply->timeout > 0)

        rt->timeout = reply->timeout;

    if (rt->server_type == RTSP_SERVER_REAL)

        rt->need_subscription = 1;

    return 0;

fail:

    for (i = 0; i < rt->nb_rtsp_streams; i++) {

        if (rt->rtsp_streams[i]->rtp_handle) {

            url_close(rt->rtsp_streams[i]->rtp_handle);

            rt->rtsp_streams[i]->rtp_handle = NULL;

        }

    }

    return err;

}