static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)

{

    ProresContext *ctx = avctx->priv_data;

    SliceContext *slice = &ctx->slices[jobnr];

    const uint8_t *buf = slice->data;

    AVFrame *pic = ctx->frame;

    int i, hdr_size, qscale, log2_chroma_blocks_per_mb;

    int luma_stride, chroma_stride;

    int y_data_size, u_data_size, v_data_size, a_data_size;

    uint8_t *dest_y, *dest_u, *dest_v, *dest_a;

    int16_t qmat_luma_scaled[64];

    int16_t qmat_chroma_scaled[64];

    int mb_x_shift;

    slice->ret = -1;

    //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n",

    //       jobnr, slice->mb_count, slice->mb_x, slice->mb_y);

    // slice header

    hdr_size = buf[0] >> 3;

    qscale = av_clip(buf[1], 1, 224);

    qscale = qscale > 128 ? qscale - 96 << 2: qscale;

    y_data_size = AV_RB16(buf + 2);

    u_data_size = AV_RB16(buf + 4);

    v_data_size = slice->data_size - y_data_size - u_data_size - hdr_size;

    if (hdr_size > 7) v_data_size = AV_RB16(buf + 6);

    a_data_size = slice->data_size - y_data_size - u_data_size -

                  v_data_size - hdr_size;

    if (y_data_size < 0 || u_data_size < 0 || v_data_size < 0

        || hdr_size+y_data_size+u_data_size+v_data_size > slice->data_size){

        av_log(avctx, AV_LOG_ERROR, "invalid plane data size\n");

        return -1;

    }

    buf += hdr_size;

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

        qmat_luma_scaled  [i] = ctx->qmat_luma  [i] * qscale;

        qmat_chroma_scaled[i] = ctx->qmat_chroma[i] * qscale;

    }

    if (ctx->frame_type == 0) {

        luma_stride   = pic->linesize[0];

        chroma_stride = pic->linesize[1];

    } else {

        luma_stride   = pic->linesize[0] << 1;

        chroma_stride = pic->linesize[1] << 1;

    }

    if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) {

        mb_x_shift = 5;

        log2_chroma_blocks_per_mb = 2;

    } else {

        mb_x_shift = 4;

        log2_chroma_blocks_per_mb = 1;

    }

    dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);

    dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);

    dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);

    dest_a = pic->data[3] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);

    if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) {

        dest_y += pic->linesize[0];

        dest_u += pic->linesize[1];

        dest_v += pic->linesize[2];

        dest_a += pic->linesize[3];

    }

    decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride,

                      buf, y_data_size, qmat_luma_scaled);

    if (!(avctx->flags & CODEC_FLAG_GRAY)) {

        decode_slice_chroma(avctx, slice, (uint16_t*)dest_u, chroma_stride,

                            buf + y_data_size, u_data_size,

                            qmat_chroma_scaled, log2_chroma_blocks_per_mb);

        decode_slice_chroma(avctx, slice, (uint16_t*)dest_v, chroma_stride,

                            buf + y_data_size + u_data_size, v_data_size,

                            qmat_chroma_scaled, log2_chroma_blocks_per_mb);

    }

    /* decode alpha plane if available */

    if (ctx->alpha_info && dest_a && a_data_size)

        decode_slice_alpha(ctx, (uint16_t*)dest_a, luma_stride,

                           buf + y_data_size + u_data_size + v_data_size,

                           a_data_size, slice->mb_count);

    slice->ret = 0;

    return 0;

}


static int img_rebase(int argc, char **argv)

{

    BlockDriverState *bs, *bs_old_backing, *bs_new_backing;

    BlockDriver *old_backing_drv, *new_backing_drv;

    char *filename;

    const char *fmt, *out_basefmt, *out_baseimg;

    int c, flags, ret;

    int unsafe = 0;

    /* Parse commandline parameters */

    fmt = NULL;

    out_baseimg = NULL;

    out_basefmt = NULL;

    for(;;) {

        c = getopt(argc, argv, "uhf:F:b:");

        if (c == -1)

            break;

        switch(c) {

        case 'h':

            help();

            return 0;

        case 'f':

            fmt = optarg;

            break;

        case 'F':

            out_basefmt = optarg;

            break;

        case 'b':

            out_baseimg = optarg;

            break;

        case 'u':

            unsafe = 1;

            break;

        }

    }

    if ((optind >= argc) || !out_baseimg)

        help();

    filename = argv[optind++];

    /*

     * Open the images.

     *

     * Ignore the old backing file for unsafe rebase in case we want to correct

     * the reference to a renamed or moved backing file.

     */

    flags = BDRV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);

    bs = bdrv_new_open(filename, fmt, flags);

    /* Find the right drivers for the backing files */

    old_backing_drv = NULL;

    new_backing_drv = NULL;

    if (!unsafe && bs->backing_format[0] != '\0') {

        old_backing_drv = bdrv_find_format(bs->backing_format);

        if (old_backing_drv == NULL) {

            error("Invalid format name: '%s'", bs->backing_format);

        }

    }

    if (out_basefmt != NULL) {

        new_backing_drv = bdrv_find_format(out_basefmt);

        if (new_backing_drv == NULL) {

            error("Invalid format name: '%s'", out_basefmt);

        }

    }

    /* For safe rebasing we need to compare old and new backing file */

    if (unsafe) {

        /* Make the compiler happy */

        bs_old_backing = NULL;

        bs_new_backing = NULL;

    } else {

        char backing_name[1024];

        bs_old_backing = bdrv_new("old_backing");

        bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));

        if (bdrv_open(bs_old_backing, backing_name, BDRV_O_FLAGS,

            old_backing_drv))

        {

            error("Could not open old backing file '%s'", backing_name);

            return -1;

        }

        bs_new_backing = bdrv_new("new_backing");

        if (bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS | BDRV_O_RDWR,

            new_backing_drv))

        {

            error("Could not open new backing file '%s'", out_baseimg);

            return -1;

        }

    }

    /*

     * Check each unallocated cluster in the COW file. If it is unallocated,

     * accesses go to the backing file. We must therefore compare this cluster

     * in the old and new backing file, and if they differ we need to copy it

     * from the old backing file into the COW file.

     *

     * If qemu-img crashes during this step, no harm is done. The content of

     * the image is the same as the original one at any time.

     */

    if (!unsafe) {

        uint64_t num_sectors;

        uint64_t sector;

        int n, n1;

        uint8_t * buf_old;

        uint8_t * buf_new;

        buf_old = qemu_malloc(IO_BUF_SIZE);

        buf_new = qemu_malloc(IO_BUF_SIZE);

        bdrv_get_geometry(bs, &num_sectors);

        for (sector = 0; sector < num_sectors; sector += n) {

            /* How many sectors can we handle with the next read? */

            if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {

                n = (IO_BUF_SIZE / 512);

            } else {

                n = num_sectors - sector;

            }

            /* If the cluster is allocated, we don't need to take action */

            if (bdrv_is_allocated(bs, sector, n, &n1)) {

                n = n1;

                continue;

            }

            /* Read old and new backing file */

            if (bdrv_read(bs_old_backing, sector, buf_old, n) < 0) {

                error("error while reading from old backing file");

            }

            if (bdrv_read(bs_new_backing, sector, buf_new, n) < 0) {

                error("error while reading from new backing file");

            }

            /* If they differ, we need to write to the COW file */

            uint64_t written = 0;

            while (written < n) {

                int pnum;

                if (compare_sectors(buf_old + written * 512,

                    buf_new + written * 512, n - written, &pnum))

                {

                    ret = bdrv_write(bs, sector + written,

                        buf_old + written * 512, pnum);

                    if (ret < 0) {

                        error("Error while writing to COW image: %s",

                            strerror(-ret));

                    }

                }

                written += pnum;

            }

        }

        qemu_free(buf_old);

        qemu_free(buf_new);

    }

    /*

     * Change the backing file. All clusters that are different from the old

     * backing file are overwritten in the COW file now, so the visible content

     * doesn't change when we switch the backing file.

     */

    ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);

    if (ret == -ENOSPC) {

        error("Could not change the backing file to '%s': No space left in "

            "the file header", out_baseimg);

    } else if (ret < 0) {

        error("Could not change the backing file to '%s': %s",

            out_baseimg, strerror(-ret));

    }

    /*

     * TODO At this point it is possible to check if any clusters that are

     * allocated in the COW file are the same in the backing file. If so, they

     * could be dropped from the COW file. Don't do this before switching the

     * backing file, in case of a crash this would lead to corruption.

     */

    /* Cleanup */

    if (!unsafe) {

        bdrv_delete(bs_old_backing);

        bdrv_delete(bs_new_backing);

    }

    bdrv_delete(bs);

    return 0;

}


static void flush_buffered(AVFormatContext *s1, int last)

{

    RTPMuxContext *s = s1->priv_data;

    if (s->buf_ptr != s->buf) {

        // If only sending one single NAL unit, skip the aggregation framing

        if (s->buffered_nals == 1)

            ff_rtp_send_data(s1, s->buf + 4, s->buf_ptr - s->buf - 4, last);

        else

            ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, last);

    }

    s->buf_ptr = s->buf;

    s->buffered_nals = 0;

}


static int vp8_lossy_decode_frame(AVCodecContext *avctx, AVFrame *p,
                                  int *got_frame, uint8_t *data_start,
                                  unsigned int data_size)
{
    WebPContext *s = avctx->priv_data;
    AVPacket pkt;
    int ret;
    if (!s->initialized) {
        ff_vp8_decode_init(avctx);
        s->initialized = 1;
    }
    avctx->pix_fmt = s->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
    s->lossless = 0;
    if (data_size > INT_MAX) {
        av_log(avctx, AV_LOG_ERROR, "unsupported chunk size\n");
        return AVERROR_PATCHWELCOME;
    }
    av_init_packet(&pkt);
    pkt.data = data_start;
    pkt.size = data_size;
    ret = ff_vp8_decode_frame(avctx, p, got_frame, &pkt);
    if (ret < 0)
        return ret;
    update_canvas_size(avctx, avctx->width, avctx->height);
    if (s->has_alpha) {
        ret = vp8_lossy_decode_alpha(avctx, p, s->alpha_data,
                                     s->alpha_data_size);
        if (ret < 0)
            return ret;
    }
    return ret;
}


static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)

{

    CcwDevice *ccw_dev = CCW_DEVICE(cdev);

    CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);

    DeviceState *parent = DEVICE(ccw_dev);

    BusState *qbus = qdev_get_parent_bus(parent);

    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);

    SubchDev *sch;

    int ret;

    Error *err = NULL;

    s390_ccw_get_dev_info(cdev, sysfsdev, &err);

    if (err) {

        goto out_err_propagate;

    }

    sch = css_create_sch(ccw_dev->devno, false, cbus->squash_mcss, &err);

    if (!sch) {

        goto out_mdevid_free;

    }

    sch->driver_data = cdev;

    sch->do_subchannel_work = do_subchannel_work_passthrough;

    ccw_dev->sch = sch;

    ret = css_sch_build_schib(sch, &cdev->hostid);

    if (ret) {

        error_setg_errno(&err, -ret, "%s: Failed to build initial schib",

                         __func__);

        goto out_err;

    }

    ck->realize(ccw_dev, &err);

    if (err) {

        goto out_err;

    }

    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,

                          parent->hotplugged, 1);

    return;

out_err:

    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);

    ccw_dev->sch = NULL;

    g_free(sch);

out_mdevid_free:

    g_free(cdev->mdevid);

out_err_propagate:

    error_propagate(errp, err);

}


static void build_pci_bus_end(PCIBus *bus, void *bus_state)

{

    AcpiBuildPciBusHotplugState *child = bus_state;

    AcpiBuildPciBusHotplugState *parent = child->parent;

    GArray *bus_table = build_alloc_array();

    DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);

    DECLARE_BITMAP(slot_device_present, PCI_SLOT_MAX);

    DECLARE_BITMAP(slot_device_system, PCI_SLOT_MAX);

    DECLARE_BITMAP(slot_device_vga, PCI_SLOT_MAX);

    DECLARE_BITMAP(slot_device_qxl, PCI_SLOT_MAX);

    uint8_t op;

    int i;

    QObject *bsel;

    GArray *method;

    bool bus_hotplug_support = false;

    if (bus->parent_dev) {

        op = 0x82; /* DeviceOp */

        build_append_nameseg(bus_table, "S%.02X_",

                             bus->parent_dev->devfn);

        build_append_byte(bus_table, 0x08); /* NameOp */

        build_append_nameseg(bus_table, "_SUN");

        build_append_value(bus_table, PCI_SLOT(bus->parent_dev->devfn), 1);

        build_append_byte(bus_table, 0x08); /* NameOp */

        build_append_nameseg(bus_table, "_ADR");

        build_append_value(bus_table, (PCI_SLOT(bus->parent_dev->devfn) << 16) |

                           PCI_FUNC(bus->parent_dev->devfn), 4);

    } else {

        op = 0x10; /* ScopeOp */;

        build_append_nameseg(bus_table, "PCI0");

    }

    bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);

    if (bsel) {

        build_append_byte(bus_table, 0x08); /* NameOp */

        build_append_nameseg(bus_table, "BSEL");

        build_append_int(bus_table, qint_get_int(qobject_to_qint(bsel)));

        memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable);

    } else {

        /* No bsel - no slots are hot-pluggable */

        memset(slot_hotplug_enable, 0x00, sizeof slot_hotplug_enable);

    }

    memset(slot_device_present, 0x00, sizeof slot_device_present);

    memset(slot_device_system, 0x00, sizeof slot_device_present);

    memset(slot_device_vga, 0x00, sizeof slot_device_vga);

    memset(slot_device_qxl, 0x00, sizeof slot_device_qxl);

    for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {

        DeviceClass *dc;

        PCIDeviceClass *pc;

        PCIDevice *pdev = bus->devices[i];

        int slot = PCI_SLOT(i);

        if (!pdev) {

            continue;

        }

        set_bit(slot, slot_device_present);

        pc = PCI_DEVICE_GET_CLASS(pdev);

        dc = DEVICE_GET_CLASS(pdev);

        if (pc->class_id == PCI_CLASS_BRIDGE_ISA) {

            set_bit(slot, slot_device_system);

        }

        if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {

            set_bit(slot, slot_device_vga);

            if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) {

                set_bit(slot, slot_device_qxl);

            }

        }

        if (!dc->hotpluggable || pc->is_bridge) {

            clear_bit(slot, slot_hotplug_enable);

        }

    }

    /* Append Device object for each slot */

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

        bool can_eject = test_bit(i, slot_hotplug_enable);

        bool present = test_bit(i, slot_device_present);

        bool vga = test_bit(i, slot_device_vga);

        bool qxl = test_bit(i, slot_device_qxl);

        bool system = test_bit(i, slot_device_system);

        if (can_eject) {

            void *pcihp = acpi_data_push(bus_table,

                                         ACPI_PCIHP_SIZEOF);

            memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);

            patch_pcihp(i, pcihp);

            bus_hotplug_support = true;

        } else if (qxl) {

            void *pcihp = acpi_data_push(bus_table,

                                         ACPI_PCIQXL_SIZEOF);

            memcpy(pcihp, ACPI_PCIQXL_AML, ACPI_PCIQXL_SIZEOF);

            patch_pciqxl(i, pcihp);

        } else if (vga) {

            void *pcihp = acpi_data_push(bus_table,

                                         ACPI_PCIVGA_SIZEOF);

            memcpy(pcihp, ACPI_PCIVGA_AML, ACPI_PCIVGA_SIZEOF);

            patch_pcivga(i, pcihp);

        } else if (system) {

            /* Nothing to do: system devices are in DSDT. */

        } else if (present) {

            void *pcihp = acpi_data_push(bus_table,

                                         ACPI_PCINOHP_SIZEOF);

            memcpy(pcihp, ACPI_PCINOHP_AML, ACPI_PCINOHP_SIZEOF);

            patch_pcinohp(i, pcihp);

        }

    }

    if (bsel) {

        method = build_alloc_method("DVNT", 2);

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

            GArray *notify;

            uint8_t op;

            if (!test_bit(i, slot_hotplug_enable)) {

                continue;

            }

            notify = build_alloc_array();

            op = 0xA0; /* IfOp */

            build_append_byte(notify, 0x7B); /* AndOp */

            build_append_byte(notify, 0x68); /* Arg0Op */

            build_append_int(notify, 0x1 << i);

            build_append_byte(notify, 0x00); /* NullName */

            build_append_byte(notify, 0x86); /* NotifyOp */

            build_append_nameseg(notify, "S%.02X_", PCI_DEVFN(i, 0));

            build_append_byte(notify, 0x69); /* Arg1Op */

            /* Pack it up */

            build_package(notify, op, 0);

            build_append_array(method, notify);

            build_free_array(notify);

        }

        build_append_and_cleanup_method(bus_table, method);

    }

    /* Append PCNT method to notify about events on local and child buses.

     * Add unconditionally for root since DSDT expects it.

     */

    if (bus_hotplug_support || child->notify_table->len || !bus->parent_dev) {

        method = build_alloc_method("PCNT", 0);

        /* If bus supports hotplug select it and notify about local events */

        if (bsel) {

            build_append_byte(method, 0x70); /* StoreOp */

            build_append_int(method, qint_get_int(qobject_to_qint(bsel)));

            build_append_nameseg(method, "BNUM");

            build_append_nameseg(method, "DVNT");

            build_append_nameseg(method, "PCIU");

            build_append_int(method, 1); /* Device Check */

            build_append_nameseg(method, "DVNT");

            build_append_nameseg(method, "PCID");

            build_append_int(method, 3); /* Eject Request */

        }

        /* Notify about child bus events in any case */

        build_append_array(method, child->notify_table);

        build_append_and_cleanup_method(bus_table, method);

        /* Append description of child buses */

        build_append_array(bus_table, child->device_table);

        /* Pack it up */

        if (bus->parent_dev) {

            build_extop_package(bus_table, op);

        } else {

            build_package(bus_table, op, 0);

        }

        /* Append our bus description to parent table */

        build_append_array(parent->device_table, bus_table);

        /* Also tell parent how to notify us, invoking PCNT method.

         * At the moment this is not needed for root as we have a single root.

         */

        if (bus->parent_dev) {

            build_append_byte(parent->notify_table, '^'); /* ParentPrefixChar */

            build_append_byte(parent->notify_table, 0x2E); /* DualNamePrefix */

            build_append_nameseg(parent->notify_table, "S%.02X_",

                                 bus->parent_dev->devfn);

            build_append_nameseg(parent->notify_table, "PCNT");

        }

    }

    build_free_array(bus_table);

    build_pci_bus_state_cleanup(child);

    g_free(child);

}


void memory_region_sync_dirty_bitmap(MemoryRegion *mr)

{

    FlatRange *fr;

    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {

        if (fr->mr == mr) {

            MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory,

                                          Forward, log_sync);

        }

    }

}


static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)

{

    SheepdogAIOCB *acb = aio_req->aiocb;

    bool create = false;

    /* check whether this request becomes a CoW one */

    if (acb->aiocb_type == AIOCB_WRITE_UDATA && is_data_obj(aio_req->oid)) {

        int idx = data_oid_to_idx(aio_req->oid);

        if (is_data_obj_writable(&s->inode, idx)) {

            goto out;

        }

        if (check_simultaneous_create(s, aio_req)) {

            return;

        }

        if (s->inode.data_vdi_id[idx]) {

            aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);

            aio_req->flags |= SD_FLAG_CMD_COW;

        }

        create = true;

    }

out:

    if (is_data_obj(aio_req->oid)) {

        add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,

                        acb->aiocb_type);

    } else {

        struct iovec iov;

        iov.iov_base = &s->inode;

        iov.iov_len = sizeof(s->inode);

        add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);

    }

}


static void *do_data_decompress(void *opaque)

{

    DecompressParam *param = opaque;

    unsigned long pagesize;

    while (!quit_decomp_thread) {

        qemu_mutex_lock(&param->mutex);

        while (!param->start && !quit_decomp_thread) {

            qemu_cond_wait(&param->cond, &param->mutex);

            pagesize = TARGET_PAGE_SIZE;

            if (!quit_decomp_thread) {

                /* uncompress() will return failed in some case, especially

                 * when the page is dirted when doing the compression, it's

                 * not a problem because the dirty page will be retransferred

                 * and uncompress() won't break the data in other pages.

                 */

                uncompress((Bytef *)param->des, &pagesize,

                           (const Bytef *)param->compbuf, param->len);

            }

            param->start = false;

        }

        qemu_mutex_unlock(&param->mutex);

    }

    return NULL;

}


static int v4l2_send_frame(AVCodecContext *avctx, const AVFrame *frame)

{

    V4L2m2mContext *s = avctx->priv_data;

    V4L2Context *const output = &s->output;

    return ff_v4l2_context_enqueue_frame(output, frame);

}


static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,

                            AVPacket *avpkt)

{

    VP8Context *s = avctx->priv_data;

    int ret, mb_x, mb_y, i, y, referenced;

    enum AVDiscard skip_thresh;

    AVFrame *curframe;

    if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0)

        return ret;

    referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT

                                || s->update_altref == VP56_FRAME_CURRENT;

    skip_thresh = !referenced ? AVDISCARD_NONREF :

                    !s->keyframe ? AVDISCARD_NONKEY : AVDISCARD_ALL;

    if (avctx->skip_frame >= skip_thresh) {

        s->invisible = 1;

        goto skip_decode;

    }

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

        if (&s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&

            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&

            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) {

            curframe = s->framep[VP56_FRAME_CURRENT] = &s->frames[i];

            break;

        }

    if (curframe->data[0])

        avctx->release_buffer(avctx, curframe);

    curframe->key_frame = s->keyframe;

    curframe->pict_type = s->keyframe ? FF_I_TYPE : FF_P_TYPE;

    curframe->reference = referenced ? 3 : 0;

    if ((ret = avctx->get_buffer(avctx, curframe))) {

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

        return ret;

    }

    // Given that arithmetic probabilities are updated every frame, it's quite likely

    // that the values we have on a random interframe are complete junk if we didn't

    // start decode on a keyframe. So just don't display anything rather than junk.

    if (!s->keyframe && (!s->framep[VP56_FRAME_PREVIOUS] ||

                         !s->framep[VP56_FRAME_GOLDEN] ||

                         !s->framep[VP56_FRAME_GOLDEN2])) {

        av_log(avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n");

        return AVERROR_INVALIDDATA;

    }

    s->linesize   = curframe->linesize[0];

    s->uvlinesize = curframe->linesize[1];

    if (!s->edge_emu_buffer)

        s->edge_emu_buffer = av_malloc(21*s->linesize);

    memset(s->top_nnz, 0, s->mb_width*sizeof(*s->top_nnz));

    // top edge of 127 for intra prediction

    if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {

        memset(curframe->data[0] - s->linesize  -1, 127, s->linesize  +1);

        memset(curframe->data[1] - s->uvlinesize-1, 127, s->uvlinesize+1);

        memset(curframe->data[2] - s->uvlinesize-1, 127, s->uvlinesize+1);

    }

    for (mb_y = 0; mb_y < s->mb_height; mb_y++) {

        VP56RangeCoder *c = &s->coeff_partition[mb_y & (s->num_coeff_partitions-1)];

        VP8Macroblock *mb = s->macroblocks + mb_y*s->mb_stride;

        uint8_t *intra4x4 = s->intra4x4_pred_mode + 4*mb_y*s->b4_stride;

        uint8_t *dst[3] = {

            curframe->data[0] + 16*mb_y*s->linesize,

            curframe->data[1] +  8*mb_y*s->uvlinesize,

            curframe->data[2] +  8*mb_y*s->uvlinesize

        };

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

        // left edge of 129 for intra prediction

        if (!(avctx->flags & CODEC_FLAG_EMU_EDGE))

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

                for (y = 0; y < 16>>!!i; y++)

                    dst[i][y*curframe->linesize[i]-1] = 129;

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

            decode_mb_mode(s, mb, mb_x, mb_y, intra4x4 + 4*mb_x);

            if (!mb->skip)

                decode_mb_coeffs(s, c, mb, s->top_nnz[mb_x], s->left_nnz);

            else {

                AV_ZERO128(s->non_zero_count_cache);    // luma

                AV_ZERO64(s->non_zero_count_cache[4]);  // chroma

            }

            if (mb->mode <= MODE_I4x4) {

                intra_predict(s, dst, mb, intra4x4 + 4*mb_x, mb_x, mb_y);

                memset(mb->bmv, 0, sizeof(mb->bmv));

            } else {

                inter_predict(s, dst, mb, mb_x, mb_y);

            }

            if (!mb->skip) {

                idct_mb(s, dst[0], dst[1], dst[2], mb);

            } else {

                AV_ZERO64(s->left_nnz);

                AV_WN64(s->top_nnz[mb_x], 0);   // array of 9, so unaligned

                // Reset DC block predictors if they would exist if the mb had coefficients

                if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) {

                    s->left_nnz[8]      = 0;

                    s->top_nnz[mb_x][8] = 0;

                }

            }

            dst[0] += 16;

            dst[1] += 8;

            dst[2] += 8;

            mb++;

        }

        if (mb_y && s->filter.level && avctx->skip_loop_filter < skip_thresh) {

            if (s->filter.simple)

                filter_mb_row_simple(s, mb_y-1);

            else

                filter_mb_row(s, mb_y-1);

        }

    }

    if (s->filter.level && avctx->skip_loop_filter < skip_thresh) {

        if (s->filter.simple)

            filter_mb_row_simple(s, mb_y-1);

        else

            filter_mb_row(s, mb_y-1);

    }

skip_decode:

    // if future frames don't use the updated probabilities,

    // reset them to the values we saved

    if (!s->update_probabilities)

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

    // check if golden and altref are swapped

    if (s->update_altref == VP56_FRAME_GOLDEN &&

        s->update_golden == VP56_FRAME_GOLDEN2)

        FFSWAP(AVFrame *, s->framep[VP56_FRAME_GOLDEN], s->framep[VP56_FRAME_GOLDEN2]);

    else {

        if (s->update_altref != VP56_FRAME_NONE)

            s->framep[VP56_FRAME_GOLDEN2] = s->framep[s->update_altref];

        if (s->update_golden != VP56_FRAME_NONE)

            s->framep[VP56_FRAME_GOLDEN] = s->framep[s->update_golden];

    }

    if (s->update_last) // move cur->prev

        s->framep[VP56_FRAME_PREVIOUS] = s->framep[VP56_FRAME_CURRENT];

    // release no longer referenced frames

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

        if (s->frames[i].data[0] &&

            &s->frames[i] != s->framep[VP56_FRAME_CURRENT] &&

            &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&

            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&

            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2])

            avctx->release_buffer(avctx, &s->frames[i]);

    if (!s->invisible) {

        *(AVFrame*)data = *s->framep[VP56_FRAME_CURRENT];

        *data_size = sizeof(AVFrame);

    }

    return avpkt->size;

}


void ff_init_vscale_pfn(SwsContext *c,

    yuv2planar1_fn yuv2plane1,

    yuv2planarX_fn yuv2planeX,

    yuv2interleavedX_fn yuv2nv12cX,

    yuv2packed1_fn yuv2packed1,

    yuv2packed2_fn yuv2packed2,

    yuv2packedX_fn yuv2packedX,

    yuv2anyX_fn yuv2anyX, int use_mmx)

{

    VScalerContext *lumCtx = NULL;

    VScalerContext *chrCtx = NULL;

    int idx = c->numDesc - (c->is_internal_gamma ? 2 : 1); //FIXME avoid hardcoding indexes

    if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) {

        if (!isGray(c->dstFormat)) {

            chrCtx = c->desc[idx].instance;

            chrCtx->filter[0] = use_mmx ? (int16_t*)c->chrMmxFilter : c->vChrFilter;

            chrCtx->filter_size = c->vChrFilterSize;

            chrCtx->filter_pos = c->vChrFilterPos;

            chrCtx->isMMX = use_mmx;

            --idx;

            if (yuv2nv12cX)               chrCtx->pfn = yuv2nv12cX;

            else if (c->vChrFilterSize == 1) chrCtx->pfn = yuv2plane1;

            else                             chrCtx->pfn = yuv2planeX;

        }

        lumCtx = c->desc[idx].instance;

        lumCtx->filter[0] = use_mmx ? (int16_t*)c->lumMmxFilter : c->vLumFilter;

        lumCtx->filter[1] = use_mmx ? (int16_t*)c->alpMmxFilter : c->vLumFilter;

        lumCtx->filter_size = c->vLumFilterSize;

        lumCtx->filter_pos = c->vLumFilterPos;

        lumCtx->isMMX = use_mmx;

        if (c->vLumFilterSize == 1) lumCtx->pfn = yuv2plane1;

        else                        lumCtx->pfn = yuv2planeX;

    } else {

        lumCtx = c->desc[idx].instance;

        chrCtx = &lumCtx[1];

        lumCtx->filter[0] = c->vLumFilter;

        lumCtx->filter_size = c->vLumFilterSize;

        lumCtx->filter_pos = c->vLumFilterPos;

        chrCtx->filter[0] = c->vChrFilter;

        chrCtx->filter_size = c->vChrFilterSize;

        chrCtx->filter_pos = c->vChrFilterPos;

        lumCtx->isMMX = use_mmx;

        chrCtx->isMMX = use_mmx;

        if (yuv2packedX) {

            if (c->yuv2packed1 && c->vLumFilterSize == 1 && c->vChrFilterSize <= 2)

                lumCtx->pfn = yuv2packed1;

            else if (c->yuv2packed2 && c->vLumFilterSize == 2 && c->vChrFilterSize == 2)

                lumCtx->pfn = yuv2packed2;

            else

                lumCtx->pfn = yuv2packedX;

        } else

            lumCtx->pfn = yuv2anyX;

    }

}


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

{

    int ret, i, type, size, pts, flags, is_audio, next, pos;

    AVStream *st = NULL;

 for(;;){

    pos = url_ftell(s->pb);

    url_fskip(s->pb, 4); /* size of previous packet */

    type = get_byte(s->pb);

    size = get_be24(s->pb);

    pts = get_be24(s->pb);

    pts |= get_byte(s->pb) << 24;

//    av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, pts:%d\n", type, size, pts);

    if (url_feof(s->pb))

        return AVERROR(EIO);

    url_fskip(s->pb, 3); /* stream id, always 0 */

    flags = 0;

    if(size == 0)

        continue;

    next= size + url_ftell(s->pb);

    if (type == FLV_TAG_TYPE_AUDIO) {

        is_audio=1;

        flags = get_byte(s->pb);

    } else if (type == FLV_TAG_TYPE_VIDEO) {

        is_audio=0;

        flags = get_byte(s->pb);

    } else {

        if (type == FLV_TAG_TYPE_META && size > 13+1+4)

            flv_read_metabody(s, next);

        else /* skip packet */

            av_log(s, AV_LOG_ERROR, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags);

        url_fseek(s->pb, next, SEEK_SET);

        continue;

    }

    /* now find stream */

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

        st = s->streams[i];

        if (st->id == is_audio)

            break;

    }

    if(i == s->nb_streams){

        av_log(NULL, AV_LOG_ERROR, "invalid stream\n");

        st= create_stream(s, is_audio);

        s->ctx_flags &= ~AVFMTCTX_NOHEADER;

    }

//    av_log(NULL, AV_LOG_DEBUG, "%d %X %d \n", is_audio, flags, st->discard);

    if(  (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY ||         is_audio))

       ||(st->discard >= AVDISCARD_BIDIR  &&  ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio))

       || st->discard >= AVDISCARD_ALL

       ){

        url_fseek(s->pb, next, SEEK_SET);

        continue;

    }

    if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)

        av_add_index_entry(st, pos, pts, size, 0, AVINDEX_KEYFRAME);

    break;

 }

    // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps

    if(!url_is_streamed(s->pb) && s->duration==AV_NOPTS_VALUE){

        int size;

        const int pos= url_ftell(s->pb);

        const int fsize= url_fsize(s->pb);

        url_fseek(s->pb, fsize-4, SEEK_SET);

        size= get_be32(s->pb);

        url_fseek(s->pb, fsize-3-size, SEEK_SET);

        if(size == get_be24(s->pb) + 11){

            s->duration= get_be24(s->pb) * (int64_t)AV_TIME_BASE / 1000;

        }

        url_fseek(s->pb, pos, SEEK_SET);

    }

    if(is_audio){

        if(!st->codec->sample_rate || !st->codec->bits_per_sample || (!st->codec->codec_id && !st->codec->codec_tag)) {

            st->codec->channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;

            if((flags & FLV_AUDIO_CODECID_MASK) == FLV_CODECID_NELLYMOSER_8HZ_MONO)

                st->codec->sample_rate= 8000;

            else

                st->codec->sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3);

            st->codec->bits_per_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;

            flv_set_audio_codec(s, st, flags & FLV_AUDIO_CODECID_MASK);

        }

    }else{

        size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK);

    }

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

    if (ret <= 0) {

        return AVERROR(EIO);

    }

    /* note: we need to modify the packet size here to handle the last

       packet */

    pkt->size = ret;

    pkt->pts = pts;

    pkt->stream_index = st->index;

    if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY))

        pkt->flags |= PKT_FLAG_KEY;

    return ret;

}


static inline void fill_caches(H264Context *h, int mb_type, int for_deblock){

    MpegEncContext * const s = &h->s;

    const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;

    int topleft_xy, top_xy, topright_xy, left_xy[2];

    int topleft_type, top_type, topright_type, left_type[2];

    int left_block[4];

    int i;

    //wow what a mess, why didnt they simplify the interlacing&intra stuff, i cant imagine that these complex rules are worth it

    if(h->sps.mb_aff){

    //FIXME

        topleft_xy = 0; /* avoid warning */

        top_xy = 0; /* avoid warning */

        topright_xy = 0; /* avoid warning */

    }else{

        topleft_xy = mb_xy-1 - s->mb_stride;

        top_xy     = mb_xy   - s->mb_stride;

        topright_xy= mb_xy+1 - s->mb_stride;

        left_xy[0]   = mb_xy-1;

        left_xy[1]   = mb_xy-1;

        left_block[0]= 0;

        left_block[1]= 1;

        left_block[2]= 2;

        left_block[3]= 3;

    }

    if(for_deblock){

        topleft_type = h->slice_table[topleft_xy ] < 255 ? s->current_picture.mb_type[topleft_xy] : 0;

        top_type     = h->slice_table[top_xy     ] < 255 ? s->current_picture.mb_type[top_xy]     : 0;

        topright_type= h->slice_table[topright_xy] < 255 ? s->current_picture.mb_type[topright_xy]: 0;

        left_type[0] = h->slice_table[left_xy[0] ] < 255 ? s->current_picture.mb_type[left_xy[0]] : 0;

        left_type[1] = h->slice_table[left_xy[1] ] < 255 ? s->current_picture.mb_type[left_xy[1]] : 0;

    }else{

        topleft_type = h->slice_table[topleft_xy ] == h->slice_num ? s->current_picture.mb_type[topleft_xy] : 0;

        top_type     = h->slice_table[top_xy     ] == h->slice_num ? s->current_picture.mb_type[top_xy]     : 0;

        topright_type= h->slice_table[topright_xy] == h->slice_num ? s->current_picture.mb_type[topright_xy]: 0;

        left_type[0] = h->slice_table[left_xy[0] ] == h->slice_num ? s->current_picture.mb_type[left_xy[0]] : 0;

        left_type[1] = h->slice_table[left_xy[1] ] == h->slice_num ? s->current_picture.mb_type[left_xy[1]] : 0;

    }

    if(IS_INTRA(mb_type)){

        h->topleft_samples_available=

        h->top_samples_available=

        h->left_samples_available= 0xFFFF;

        h->topright_samples_available= 0xEEEA;

        if(!IS_INTRA(top_type) && (top_type==0 || h->pps.constrained_intra_pred)){

            h->topleft_samples_available= 0xB3FF;

            h->top_samples_available= 0x33FF;

            h->topright_samples_available= 0x26EA;

        }

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

            if(!IS_INTRA(left_type[i]) && (left_type[i]==0 || h->pps.constrained_intra_pred)){

                h->topleft_samples_available&= 0xDF5F;

                h->left_samples_available&= 0x5F5F;

            }

        }

        if(!IS_INTRA(topleft_type) && (topleft_type==0 || h->pps.constrained_intra_pred))

            h->topleft_samples_available&= 0x7FFF;

        if(!IS_INTRA(topright_type) && (topright_type==0 || h->pps.constrained_intra_pred))

            h->topright_samples_available&= 0xFBFF;

        if(IS_INTRA4x4(mb_type)){

            if(IS_INTRA4x4(top_type)){

                h->intra4x4_pred_mode_cache[4+8*0]= h->intra4x4_pred_mode[top_xy][4];

                h->intra4x4_pred_mode_cache[5+8*0]= h->intra4x4_pred_mode[top_xy][5];

                h->intra4x4_pred_mode_cache[6+8*0]= h->intra4x4_pred_mode[top_xy][6];

                h->intra4x4_pred_mode_cache[7+8*0]= h->intra4x4_pred_mode[top_xy][3];

            }else{

                int pred;

                if(!top_type || (IS_INTER(top_type) && h->pps.constrained_intra_pred))

                    pred= -1;

                else{

                    pred= 2;

                }

                h->intra4x4_pred_mode_cache[4+8*0]=

                h->intra4x4_pred_mode_cache[5+8*0]=

                h->intra4x4_pred_mode_cache[6+8*0]=

                h->intra4x4_pred_mode_cache[7+8*0]= pred;

            }

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

                if(IS_INTRA4x4(left_type[i])){

                    h->intra4x4_pred_mode_cache[3+8*1 + 2*8*i]= h->intra4x4_pred_mode[left_xy[i]][left_block[0+2*i]];

                    h->intra4x4_pred_mode_cache[3+8*2 + 2*8*i]= h->intra4x4_pred_mode[left_xy[i]][left_block[1+2*i]];

                }else{

                    int pred;

                    if(!left_type[i] || (IS_INTER(left_type[i]) && h->pps.constrained_intra_pred))

                        pred= -1;

                    else{

                        pred= 2;

                    }

                    h->intra4x4_pred_mode_cache[3+8*1 + 2*8*i]=

                    h->intra4x4_pred_mode_cache[3+8*2 + 2*8*i]= pred;

                }

            }

        }

    }

/*

0 . T T. T T T T

1 L . .L . . . .

2 L . .L . . . .

3 . T TL . . . .

4 L . .L . . . .

5 L . .. . . . .

*/

//FIXME constraint_intra_pred & partitioning & nnz (lets hope this is just a typo in the spec)

    if(top_type){

        h->non_zero_count_cache[4+8*0]= h->non_zero_count[top_xy][0];

        h->non_zero_count_cache[5+8*0]= h->non_zero_count[top_xy][1];

        h->non_zero_count_cache[6+8*0]= h->non_zero_count[top_xy][2];

        h->non_zero_count_cache[7+8*0]= h->non_zero_count[top_xy][3];

        h->non_zero_count_cache[1+8*0]= h->non_zero_count[top_xy][7];

        h->non_zero_count_cache[2+8*0]= h->non_zero_count[top_xy][8];

        h->non_zero_count_cache[1+8*3]= h->non_zero_count[top_xy][10];

        h->non_zero_count_cache[2+8*3]= h->non_zero_count[top_xy][11];

        h->top_cbp= h->cbp_table[top_xy];

    }else{

        h->non_zero_count_cache[4+8*0]=

        h->non_zero_count_cache[5+8*0]=

        h->non_zero_count_cache[6+8*0]=

        h->non_zero_count_cache[7+8*0]=

        h->non_zero_count_cache[1+8*0]=

        h->non_zero_count_cache[2+8*0]=

        h->non_zero_count_cache[1+8*3]=

        h->non_zero_count_cache[2+8*3]= h->pps.cabac && !IS_INTRA(mb_type) ? 0 : 64;

        if(IS_INTRA(mb_type)) h->top_cbp= 0x1C0;

        else                  h->top_cbp= 0;

    }

    if(left_type[0]){

        h->non_zero_count_cache[3+8*1]= h->non_zero_count[left_xy[0]][6];

        h->non_zero_count_cache[3+8*2]= h->non_zero_count[left_xy[0]][5];

        h->non_zero_count_cache[0+8*1]= h->non_zero_count[left_xy[0]][9]; //FIXME left_block

        h->non_zero_count_cache[0+8*4]= h->non_zero_count[left_xy[0]][12];

        h->left_cbp= h->cbp_table[left_xy[0]]; //FIXME interlacing

    }else{

        h->non_zero_count_cache[3+8*1]=

        h->non_zero_count_cache[3+8*2]=

        h->non_zero_count_cache[0+8*1]=

        h->non_zero_count_cache[0+8*4]= h->pps.cabac && !IS_INTRA(mb_type) ? 0 : 64;

        if(IS_INTRA(mb_type)) h->left_cbp= 0x1C0;//FIXME interlacing

        else                  h->left_cbp= 0;

    }

    if(left_type[1]){

        h->non_zero_count_cache[3+8*3]= h->non_zero_count[left_xy[1]][4];

        h->non_zero_count_cache[3+8*4]= h->non_zero_count[left_xy[1]][3];

        h->non_zero_count_cache[0+8*2]= h->non_zero_count[left_xy[1]][8];

        h->non_zero_count_cache[0+8*5]= h->non_zero_count[left_xy[1]][11];

    }else{

        h->non_zero_count_cache[3+8*3]=

        h->non_zero_count_cache[3+8*4]=

        h->non_zero_count_cache[0+8*2]=

        h->non_zero_count_cache[0+8*5]= h->pps.cabac && !IS_INTRA(mb_type) ? 0 : 64;

    }

#if 1

    //FIXME direct mb can skip much of this

    if(IS_INTER(mb_type) || (IS_DIRECT(mb_type) && h->direct_spatial_mv_pred)){

        int list;

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

            if((!IS_8X8(mb_type)) && !USES_LIST(mb_type, list) && !IS_DIRECT(mb_type)){

                /*if(!h->mv_cache_clean[list]){

                    memset(h->mv_cache [list],  0, 8*5*2*sizeof(int16_t)); //FIXME clean only input? clean at all?

                    memset(h->ref_cache[list], PART_NOT_AVAILABLE, 8*5*sizeof(int8_t));

                    h->mv_cache_clean[list]= 1;

                }*/

                continue;

            }

            h->mv_cache_clean[list]= 0;

            if(IS_INTER(topleft_type)){

                const int b_xy = h->mb2b_xy[topleft_xy] + 3 + 3*h->b_stride;

                const int b8_xy= h->mb2b8_xy[topleft_xy] + 1 + h->b8_stride;

                *(uint32_t*)h->mv_cache[list][scan8[0] - 1 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy];

                h->ref_cache[list][scan8[0] - 1 - 1*8]= s->current_picture.ref_index[list][b8_xy];

            }else{

                *(uint32_t*)h->mv_cache[list][scan8[0] - 1 - 1*8]= 0;

                h->ref_cache[list][scan8[0] - 1 - 1*8]= topleft_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;

            }

            if(IS_INTER(top_type)){

                const int b_xy= h->mb2b_xy[top_xy] + 3*h->b_stride;

                const int b8_xy= h->mb2b8_xy[top_xy] + h->b8_stride;

                *(uint32_t*)h->mv_cache[list][scan8[0] + 0 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + 0];

                *(uint32_t*)h->mv_cache[list][scan8[0] + 1 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + 1];

                *(uint32_t*)h->mv_cache[list][scan8[0] + 2 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + 2];

                *(uint32_t*)h->mv_cache[list][scan8[0] + 3 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + 3];

                h->ref_cache[list][scan8[0] + 0 - 1*8]=

                h->ref_cache[list][scan8[0] + 1 - 1*8]= s->current_picture.ref_index[list][b8_xy + 0];

                h->ref_cache[list][scan8[0] + 2 - 1*8]=

                h->ref_cache[list][scan8[0] + 3 - 1*8]= s->current_picture.ref_index[list][b8_xy + 1];

            }else{

                *(uint32_t*)h->mv_cache [list][scan8[0] + 0 - 1*8]=

                *(uint32_t*)h->mv_cache [list][scan8[0] + 1 - 1*8]=

                *(uint32_t*)h->mv_cache [list][scan8[0] + 2 - 1*8]=

                *(uint32_t*)h->mv_cache [list][scan8[0] + 3 - 1*8]= 0;

                *(uint32_t*)&h->ref_cache[list][scan8[0] + 0 - 1*8]= ((top_type ? LIST_NOT_USED : PART_NOT_AVAILABLE)&0xFF)*0x01010101;

            }

            if(IS_INTER(topright_type)){

                const int b_xy= h->mb2b_xy[topright_xy] + 3*h->b_stride;

                const int b8_xy= h->mb2b8_xy[topright_xy] + h->b8_stride;

                *(uint32_t*)h->mv_cache[list][scan8[0] + 4 - 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy];

                h->ref_cache[list][scan8[0] + 4 - 1*8]= s->current_picture.ref_index[list][b8_xy];

            }else{

                *(uint32_t*)h->mv_cache [list][scan8[0] + 4 - 1*8]= 0;

                h->ref_cache[list][scan8[0] + 4 - 1*8]= topright_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;

            }

            //FIXME unify cleanup or sth

            if(IS_INTER(left_type[0])){

                const int b_xy= h->mb2b_xy[left_xy[0]] + 3;

                const int b8_xy= h->mb2b8_xy[left_xy[0]] + 1;

                *(uint32_t*)h->mv_cache[list][scan8[0] - 1 + 0*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[0]];

                *(uint32_t*)h->mv_cache[list][scan8[0] - 1 + 1*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[1]];

                h->ref_cache[list][scan8[0] - 1 + 0*8]=

                h->ref_cache[list][scan8[0] - 1 + 1*8]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[0]>>1)];

            }else{

                *(uint32_t*)h->mv_cache [list][scan8[0] - 1 + 0*8]=

                *(uint32_t*)h->mv_cache [list][scan8[0] - 1 + 1*8]= 0;

                h->ref_cache[list][scan8[0] - 1 + 0*8]=

                h->ref_cache[list][scan8[0] - 1 + 1*8]= left_type[0] ? LIST_NOT_USED : PART_NOT_AVAILABLE;

            }

            if(IS_INTER(left_type[1])){

                const int b_xy= h->mb2b_xy[left_xy[1]] + 3;

                const int b8_xy= h->mb2b8_xy[left_xy[1]] + 1;

                *(uint32_t*)h->mv_cache[list][scan8[0] - 1 + 2*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[2]];

                *(uint32_t*)h->mv_cache[list][scan8[0] - 1 + 3*8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[3]];

                h->ref_cache[list][scan8[0] - 1 + 2*8]=

                h->ref_cache[list][scan8[0] - 1 + 3*8]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[2]>>1)];

            }else{

                *(uint32_t*)h->mv_cache [list][scan8[0] - 1 + 2*8]=

                *(uint32_t*)h->mv_cache [list][scan8[0] - 1 + 3*8]= 0;

                h->ref_cache[list][scan8[0] - 1 + 2*8]=

                h->ref_cache[list][scan8[0] - 1 + 3*8]= left_type[0] ? LIST_NOT_USED : PART_NOT_AVAILABLE;

            }

            if(for_deblock)

                continue;

            h->ref_cache[list][scan8[5 ]+1] =

            h->ref_cache[list][scan8[7 ]+1] =

            h->ref_cache[list][scan8[13]+1] =  //FIXME remove past 3 (init somewher else)

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

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

            *(uint32_t*)h->mv_cache [list][scan8[5 ]+1]=

            *(uint32_t*)h->mv_cache [list][scan8[7 ]+1]=

            *(uint32_t*)h->mv_cache [list][scan8[13]+1]= //FIXME remove past 3 (init somewher else)

            *(uint32_t*)h->mv_cache [list][scan8[4 ]]=

            *(uint32_t*)h->mv_cache [list][scan8[12]]= 0;

            if( h->pps.cabac ) {

                /* XXX beurk, Load mvd */

                if(IS_INTER(topleft_type)){

                    const int b_xy = h->mb2b_xy[topleft_xy] + 3 + 3*h->b_stride;

                    *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy];

                }else{

                    *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 - 1*8]= 0;

                }

                if(IS_INTER(top_type)){

                    const int b_xy= h->mb2b_xy[top_xy] + 3*h->b_stride;

                    *(uint32_t*)h->mvd_cache[list][scan8[0] + 0 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + 0];

                    *(uint32_t*)h->mvd_cache[list][scan8[0] + 1 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + 1];

                    *(uint32_t*)h->mvd_cache[list][scan8[0] + 2 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + 2];

                    *(uint32_t*)h->mvd_cache[list][scan8[0] + 3 - 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + 3];

                }else{

                    *(uint32_t*)h->mvd_cache [list][scan8[0] + 0 - 1*8]=

                    *(uint32_t*)h->mvd_cache [list][scan8[0] + 1 - 1*8]=

                    *(uint32_t*)h->mvd_cache [list][scan8[0] + 2 - 1*8]=

                    *(uint32_t*)h->mvd_cache [list][scan8[0] + 3 - 1*8]= 0;

                }

                if(IS_INTER(left_type[0])){

                    const int b_xy= h->mb2b_xy[left_xy[0]] + 3;

                    *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 + 0*8]= *(uint32_t*)h->mvd_table[list][b_xy + h->b_stride*left_block[0]];

                    *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 + 1*8]= *(uint32_t*)h->mvd_table[list][b_xy + h->b_stride*left_block[1]];

                }else{

                    *(uint32_t*)h->mvd_cache [list][scan8[0] - 1 + 0*8]=

                    *(uint32_t*)h->mvd_cache [list][scan8[0] - 1 + 1*8]= 0;

                }

                if(IS_INTER(left_type[1])){

                    const int b_xy= h->mb2b_xy[left_xy[1]] + 3;

                    *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 + 2*8]= *(uint32_t*)h->mvd_table[list][b_xy + h->b_stride*left_block[2]];

                    *(uint32_t*)h->mvd_cache[list][scan8[0] - 1 + 3*8]= *(uint32_t*)h->mvd_table[list][b_xy + h->b_stride*left_block[3]];

                }else{

                    *(uint32_t*)h->mvd_cache [list][scan8[0] - 1 + 2*8]=

                    *(uint32_t*)h->mvd_cache [list][scan8[0] - 1 + 3*8]= 0;

                }

                *(uint32_t*)h->mvd_cache [list][scan8[5 ]+1]=

                *(uint32_t*)h->mvd_cache [list][scan8[7 ]+1]=

                *(uint32_t*)h->mvd_cache [list][scan8[13]+1]= //FIXME remove past 3 (init somewher else)

                *(uint32_t*)h->mvd_cache [list][scan8[4 ]]=

                *(uint32_t*)h->mvd_cache [list][scan8[12]]= 0;

                if(h->slice_type == B_TYPE){

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

                    if(IS_DIRECT(top_type)){

                        *(uint32_t*)&h->direct_cache[scan8[0] - 1*8]= 0x01010101;

                    }else if(IS_8X8(top_type)){

                        int b8_xy = h->mb2b8_xy[top_xy] + h->b8_stride;

                        h->direct_cache[scan8[0] + 0 - 1*8]= h->direct_table[b8_xy];

                        h->direct_cache[scan8[0] + 2 - 1*8]= h->direct_table[b8_xy + 1];

                    }else{

                        *(uint32_t*)&h->direct_cache[scan8[0] - 1*8]= 0;

                    }

                    //FIXME interlacing

                    if(IS_DIRECT(left_type[0])){

                        h->direct_cache[scan8[0] - 1 + 0*8]=

                        h->direct_cache[scan8[0] - 1 + 2*8]= 1;

                    }else if(IS_8X8(left_type[0])){

                        int b8_xy = h->mb2b8_xy[left_xy[0]] + 1;

                        h->direct_cache[scan8[0] - 1 + 0*8]= h->direct_table[b8_xy];

                        h->direct_cache[scan8[0] - 1 + 2*8]= h->direct_table[b8_xy + h->b8_stride];

                    }else{

                        h->direct_cache[scan8[0] - 1 + 0*8]=

                        h->direct_cache[scan8[0] - 1 + 2*8]= 0;

                    }

                }

            }

        }

    }

#endif

}


static int update_dimensions(VP8Context *s, int width, int height)

{

    int i;

    if (avcodec_check_dimensions(s->avctx, width, height))

        return AVERROR_INVALIDDATA;

    vp8_decode_flush(s->avctx);

    avcodec_set_dimensions(s->avctx, width, height);

    s->mb_width  = (s->avctx->coded_width +15) / 16;

    s->mb_height = (s->avctx->coded_height+15) / 16;

    // we allocate a border around the top/left of intra4x4 modes

    // this is 4 blocks for intra4x4 to keep 4-byte alignment for fill_rectangle

    s->mb_stride = s->mb_width+1;

    s->b4_stride = 4*s->mb_stride;

    s->macroblocks_base        = av_mallocz(s->mb_stride*(s->mb_height+1)*sizeof(*s->macroblocks));

    s->intra4x4_pred_mode_base = av_mallocz(s->b4_stride*(4*s->mb_height+1));

    s->top_nnz                 = av_mallocz(s->mb_width*sizeof(*s->top_nnz));

    if (!s->macroblocks_base || !s->intra4x4_pred_mode_base || !s->top_nnz)

        return AVERROR(ENOMEM);

    s->macroblocks        = s->macroblocks_base        + 1 + s->mb_stride;

    s->intra4x4_pred_mode = s->intra4x4_pred_mode_base + 4 + s->b4_stride;

    memset(s->intra4x4_pred_mode_base, DC_PRED, s->b4_stride);

    for (i = 0; i < 4*s->mb_height; i++)

        s->intra4x4_pred_mode[i*s->b4_stride-1] = DC_PRED;

    return 0;

}


static void predictor_decompress_fir_adapt(int32_t *error_buffer,

                                           int32_t *buffer_out,

                                           int output_size,

                                           int readsamplesize,

                                           int16_t *predictor_coef_table,

                                           int predictor_coef_num,

                                           int predictor_quantitization)

{

    int i;

    /* first sample always copies */

    *buffer_out = *error_buffer;

    if (!predictor_coef_num) {

        if (output_size <= 1)

            return;

        memcpy(&buffer_out[1], &error_buffer[1],

               (output_size - 1) * sizeof(*buffer_out));

        return;

    }

    if (predictor_coef_num == 31) {

        /* simple 1st-order prediction */

        if (output_size <= 1)

            return;

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

            buffer_out[i] = sign_extend(buffer_out[i - 1] + error_buffer[i],

                                        readsamplesize);

        }

        return;

    }

    /* read warm-up samples */

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

        buffer_out[i + 1] = sign_extend(buffer_out[i] + error_buffer[i + 1],

                                        readsamplesize);

    }

    /* NOTE: 4 and 8 are very common cases that could be optimized. */

    /* general case */

    for (i = predictor_coef_num; i < output_size - 1; i++) {

        int j;

        int val = 0;

        int error_val = error_buffer[i + 1];

        int error_sign;

        int d = buffer_out[i - predictor_coef_num];

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

            val += (buffer_out[i - j] - d) *

                   predictor_coef_table[j];

        }

        val = (val + (1 << (predictor_quantitization - 1))) >>

              predictor_quantitization;

        val += d + error_val;

        buffer_out[i + 1] = sign_extend(val, readsamplesize);

        /* adapt LPC coefficients */

        error_sign = sign_only(error_val);

        if (error_sign) {

            for (j = predictor_coef_num - 1; j >= 0 && error_val * error_sign > 0; j--) {

                int sign;

                val  = d - buffer_out[i - j];

                sign = sign_only(val) * error_sign;

                predictor_coef_table[j] -= sign;

                val *= sign;

                error_val -= ((val >> predictor_quantitization) *

                              (predictor_coef_num - j));

            }

        }

    }

}


static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc,

                                  int nb_samples, int *buf_linesize)

{

    int64_t audio_buf_samples;

    int audio_buf_size;

    /* calculate required number of samples to allocate */

    audio_buf_samples = ((int64_t)nb_samples * enc->sample_rate + dec->sample_rate) /

                        dec->sample_rate;

    audio_buf_samples = 4 * audio_buf_samples + 10000; // safety factors for resampling

    audio_buf_samples = FFMAX(audio_buf_samples, enc->frame_size);

    if (audio_buf_samples > INT_MAX)

        return AVERROR(EINVAL);

    audio_buf_size = av_samples_get_buffer_size(buf_linesize, enc->channels,

                                                audio_buf_samples,

                                                enc->sample_fmt, 0);

    if (audio_buf_size < 0)

        return audio_buf_size;

    av_fast_malloc(&audio_buf, &allocated_audio_buf_size, audio_buf_size);

    if (!audio_buf)

        return AVERROR(ENOMEM);

    return 0;

}


struct omap_mmc_s *omap_mmc_init(hwaddr base,

                MemoryRegion *sysmem,

                BlockBackend *blk,

                qemu_irq irq, qemu_irq dma[], omap_clk clk)

{

    struct omap_mmc_s *s = (struct omap_mmc_s *)

            g_malloc0(sizeof(struct omap_mmc_s));

    s->irq = irq;

    s->dma = dma;

    s->clk = clk;

    s->lines = 1;	/* TODO: needs to be settable per-board */

    s->rev = 1;

    omap_mmc_reset(s);

    memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc", 0x800);

    memory_region_add_subregion(sysmem, base, &s->iomem);

    /* Instantiate the storage */

    s->card = sd_init(blk, false);

    if (s->card == NULL) {

        exit(1);

    }

    return s;

}


static int nut_write_header(AVFormatContext * avf) {

    NUTContext * priv = avf->priv_data;

    AVIOContext * bc = avf->pb;

    nut_muxer_opts_tt mopts = {

        .output = {

            .priv = bc,

            .write = av_write,

        },

        .alloc = { av_malloc, av_realloc, av_free },

        .write_index = 1,

        .realtime_stream = 0,

        .max_distance = 32768,

        .fti = NULL,

    };

    nut_stream_header_tt * s;

    int i;

    priv->s = s = av_mallocz((avf->nb_streams + 1) * sizeof*s);

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

        AVCodecContext * codec = avf->streams[i]->codec;

        int j;

        int fourcc = 0;

        int num, denom, ssize;

        s[i].type = codec->codec_type == AVMEDIA_TYPE_VIDEO ? NUT_VIDEO_CLASS : NUT_AUDIO_CLASS;

        if (codec->codec_tag) fourcc = codec->codec_tag;

        else fourcc = ff_codec_get_tag(nut_tags, codec->codec_id);

        if (!fourcc) {

            if (codec->codec_type == AVMEDIA_TYPE_VIDEO) fourcc = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id);

            if (codec->codec_type == AVMEDIA_TYPE_AUDIO) fourcc = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id);

        }

        s[i].fourcc_len = 4;

        s[i].fourcc = av_malloc(s[i].fourcc_len);

        for (j = 0; j < s[i].fourcc_len; j++) s[i].fourcc[j] = (fourcc >> (j*8)) & 0xFF;

        ff_parse_specific_params(codec, &num, &ssize, &denom);

        avpriv_set_pts_info(avf->streams[i], 60, denom, num);

        s[i].time_base.num = denom;

        s[i].time_base.den = num;

        s[i].fixed_fps = 0;

        s[i].decode_delay = codec->has_b_frames;

        s[i].codec_specific_len = codec->extradata_size;

        s[i].codec_specific = codec->extradata;

        if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {

            s[i].width = codec->width;

            s[i].height = codec->height;

            s[i].sample_width = 0;

            s[i].sample_height = 0;

            s[i].colorspace_type = 0;

        } else {

            s[i].samplerate_num = codec->sample_rate;

            s[i].samplerate_denom = 1;

            s[i].channel_count = codec->channels;

        }

    }

    s[avf->nb_streams].type = -1;

    priv->nut = nut_muxer_init(&mopts, s, NULL);

    return 0;

}


static inline int RENAME(yuv420_rgb16)(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,

             int srcSliceH, uint8_t* dst[], int dstStride[]){

    int y, h_size;

    if(c->srcFormat == PIX_FMT_YUV422P){

	srcStride[1] *= 2;

	srcStride[2] *= 2;

    }

    h_size= (c->dstW+7)&~7;

    if(h_size*2 > dstStride[0]) h_size-=8;

    __asm__ __volatile__ ("pxor %mm4, %mm4;" /* zero mm4 */ );

//printf("%X %X %X %X %X %X %X %X %X %X\n", (int)&c->redDither, (int)&b5Dither, (int)src[0], (int)src[1], (int)src[2], (int)dst[0],

//srcStride[0],srcStride[1],srcStride[2],dstStride[0]);

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

	uint8_t *_image = dst[0] + (y+srcSliceY)*dstStride[0];

	uint8_t *_py = src[0] + y*srcStride[0];

	uint8_t *_pu = src[1] + (y>>1)*srcStride[1];

	uint8_t *_pv = src[2] + (y>>1)*srcStride[2];

	long index= -h_size/2;

	b5Dither= dither8[y&1];

	g6Dither= dither4[y&1];

	g5Dither= dither8[y&1];

	r5Dither= dither8[(y+1)&1];

	    /* this mmx assembly code deals with SINGLE scan line at a time, it convert 8

	       pixels in each iteration */

	    __asm__ __volatile__ (

	/* load data for start of next scan line */

		     "movd (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */

		     "movd (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */

		     "movq (%5, %0, 2), %%mm6;" /* Load 8  Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */

//		    ".balign 16			\n\t"

		    "1:				\n\t"

/* no speed diference on my p3@500 with prefetch,

 * if it is faster for anyone with -benchmark then tell me

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

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

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

*/

YUV2RGB

#ifdef DITHER1XBPP

			"paddusb "MANGLE(b5Dither)", %%mm0;"

			"paddusb "MANGLE(g6Dither)", %%mm2;"

			"paddusb "MANGLE(r5Dither)", %%mm1;"

#endif

		     /* mask unneeded bits off */

		     "pand "MANGLE(mmx_redmask)", %%mm0;" /* b7b6b5b4 b3_0_0_0 b7b6b5b4 b3_0_0_0 */

		     "pand "MANGLE(mmx_grnmask)", %%mm2;" /* g7g6g5g4 g3g2_0_0 g7g6g5g4 g3g2_0_0 */

		     "pand "MANGLE(mmx_redmask)", %%mm1;" /* r7r6r5r4 r3_0_0_0 r7r6r5r4 r3_0_0_0 */

		     "psrlw $3,%%mm0;" /* 0_0_0_b7 b6b5b4b3 0_0_0_b7 b6b5b4b3 */

		     "pxor %%mm4, %%mm4;" /* zero mm4 */

		     "movq %%mm0, %%mm5;" /* Copy B7-B0 */

		     "movq %%mm2, %%mm7;" /* Copy G7-G0 */

		     /* convert rgb24 plane to rgb16 pack for pixel 0-3 */

		     "punpcklbw %%mm4, %%mm2;" /* 0_0_0_0 0_0_0_0 g7g6g5g4 g3g2_0_0 */

		     "punpcklbw %%mm1, %%mm0;" /* r7r6r5r4 r3_0_0_0 0_0_0_b7 b6b5b4b3 */

		     "psllw $3, %%mm2;" /* 0_0_0_0 0_g7g6g5 g4g3g2_0 0_0_0_0 */

		     "por %%mm2, %%mm0;" /* r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3 */

		     "movq 8 (%5, %0, 2), %%mm6;" /* Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */

		     MOVNTQ " %%mm0, (%1);" /* store pixel 0-3 */

		     /* convert rgb24 plane to rgb16 pack for pixel 0-3 */

		     "punpckhbw %%mm4, %%mm7;" /* 0_0_0_0 0_0_0_0 g7g6g5g4 g3g2_0_0 */

		     "punpckhbw %%mm1, %%mm5;" /* r7r6r5r4 r3_0_0_0 0_0_0_b7 b6b5b4b3 */

		     "psllw $3, %%mm7;" /* 0_0_0_0 0_g7g6g5 g4g3g2_0 0_0_0_0 */

		     "movd 4 (%2, %0), %%mm0;" /* Load 4 Cb 00 00 00 00 u3 u2 u1 u0 */

		     "por %%mm7, %%mm5;" /* r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3 */

		     "movd 4 (%3, %0), %%mm1;" /* Load 4 Cr 00 00 00 00 v3 v2 v1 v0 */

		     MOVNTQ " %%mm5, 8 (%1);" /* store pixel 4-7 */

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

		     "add $4, %0			\n\t"

		     " js 1b				\n\t"

		     : "+r" (index), "+r" (_image)

		     : "r" (_pu - index), "r" (_pv - index), "r"(&c->redDither), "r" (_py - 2*index)

		     );

    }

    __asm__ __volatile__ (EMMS);

    return srcSliceH;

}


static void pc_machine_class_init(ObjectClass *oc, void *data)

{

    MachineClass *mc = MACHINE_CLASS(oc);

    PCMachineClass *pcmc = PC_MACHINE_CLASS(oc);

    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);

    pcmc->inter_dimm_gap = true;

    pcmc->get_hotplug_handler = mc->get_hotplug_handler;

    mc->get_hotplug_handler = pc_get_hotpug_handler;

    mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id;

    mc->default_boot_order = "cad";

    mc->hot_add_cpu = pc_hot_add_cpu;

    mc->max_cpus = 255;

    mc->reset = pc_machine_reset;

    hc->plug = pc_machine_device_plug_cb;

    hc->unplug_request = pc_machine_device_unplug_request_cb;

    hc->unplug = pc_machine_device_unplug_cb;

}


static void test_none(void)

{

    struct qdist dist;

    char *pr;

    qdist_init(&dist);

    g_assert(isnan(qdist_avg(&dist)));

    g_assert(isnan(qdist_xmin(&dist)));

    g_assert(isnan(qdist_xmax(&dist)));

    pr = qdist_pr_plain(&dist, 0);

    g_assert(pr == NULL);

    pr = qdist_pr_plain(&dist, 2);

    g_assert(pr == NULL);

    qdist_destroy(&dist);

}


void process_pending_signals(CPUArchState *cpu_env)

{

    CPUState *cpu = ENV_GET_CPU(cpu_env);

    int sig;

    TaskState *ts = cpu->opaque;

    if (!ts->signal_pending)

        return;

    /* FIXME: This is not threadsafe.  */

    for(sig = 1; sig <= TARGET_NSIG; sig++) {

        if (ts->sigtab[sig - 1].pending) {

            handle_pending_signal(cpu_env, sig);

            return;

        }

    }

    /* if no signal is pending, just return */

    ts->signal_pending = 0;

    return;

}


ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,

                                   ram_addr_t size, void *host)

{

    RAMBlock *new_block, *block;

    size = TARGET_PAGE_ALIGN(size);

    new_block = qemu_mallocz(sizeof(*new_block));

    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {

        char *id = dev->parent_bus->info->get_dev_path(dev);

        if (id) {

            snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);

            qemu_free(id);

    pstrcat(new_block->idstr, sizeof(new_block->idstr), name);

    QLIST_FOREACH(block, &ram_list.blocks, next) {

        if (!strcmp(block->idstr, new_block->idstr)) {

            fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",

                    new_block->idstr);

    new_block->offset = find_ram_offset(size);

    if (host) {

        new_block->host = host;

        new_block->flags |= RAM_PREALLOC_MASK;

    } else {

        if (mem_path) {

#if defined (__linux__) && !defined(TARGET_S390X)

            new_block->host = file_ram_alloc(new_block, size, mem_path);

            if (!new_block->host) {

                new_block->host = qemu_vmalloc(size);

                qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);

#else

            fprintf(stderr, "-mem-path option unsupported\n");

            exit(1);

#endif

        } else {

#if defined(TARGET_S390X) && defined(CONFIG_KVM)

            /* S390 KVM requires the topmost vma of the RAM to be smaller than

               an system defined value, which is at least 256GB. Larger systems

               have larger values. We put the guest between the end of data

               segment (system break) and this value. We use 32GB as a base to

               have enough room for the system break to grow. */

            new_block->host = mmap((void*)0x800000000, size,

                                   PROT_EXEC|PROT_READ|PROT_WRITE,

                                   MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);

#else

            if (xen_mapcache_enabled()) {

                xen_ram_alloc(new_block->offset, size);

            } else {

                new_block->host = qemu_vmalloc(size);

#endif

            qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);

    new_block->length = size;

    QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);

    ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,

                                       last_ram_offset() >> TARGET_PAGE_BITS);

    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),

           0xff, size >> TARGET_PAGE_BITS);

    if (kvm_enabled())

        kvm_setup_guest_memory(new_block->host, size);

    return new_block->offset;


char *qmp_memchar_read(const char *device, int64_t size,

                       bool has_format, enum DataFormat format,

                       Error **errp)

{

    CharDriverState *chr;

    uint8_t *read_data;

    size_t count;

    char *data;

    chr = qemu_chr_find(device);

    if (!chr) {

        error_setg(errp, "Device '%s' not found", device);

        return NULL;

    }

    if (qemu_is_chr(chr, "memory")) {

        error_setg(errp,"%s is not memory char device", device);

        return NULL;

    }

    if (size <= 0) {

        error_setg(errp, "size must be greater than zero");

        return NULL;

    }

    count = qemu_chr_cirmem_count(chr);

    if (count == 0) {

        return g_strdup("");

    }

    size = size > count ? count : size;

    read_data = g_malloc0(size + 1);

    cirmem_chr_read(chr, read_data, size);

    if (has_format && (format == DATA_FORMAT_BASE64)) {

        data = g_base64_encode(read_data, size);

    } else {

        data = (char *)read_data;

    }

    return data;

}


static void xbzrle_cache_zero_page(ram_addr_t current_addr)

{

    if (ram_bulk_stage || !migrate_use_xbzrle()) {

        return;

    }

    /* We don't care if this fails to allocate a new cache page

     * as long as it updated an old one */

    cache_insert(XBZRLE.cache, current_addr, ZERO_TARGET_PAGE);

}


static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)

{

    /* Flush the whole TB as this will not have race conditions

     * even if we don't have proper locking yet.

     * Ideally we would just invalidate the TBs for the

     * specified PC.

     */

    tb_flush(cpu);

}


static void vfio_bar_quirk_teardown(VFIODevice *vdev, int nr)

{

    VFIOBAR *bar = &vdev->bars[nr];

    while (!QLIST_EMPTY(&bar->quirks)) {

        VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);

        memory_region_del_subregion(&bar->mem, &quirk->mem);

        QLIST_REMOVE(quirk, next);

        g_free(quirk);

    }

}


static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,

                                          void *opaque)

{

    PCIBus *sec_bus;

    sPAPRFDT *p = opaque;

    int offset;

    sPAPRFDT s_fdt;

    uint32_t drc_index = spapr_phb_get_pci_drc_index(p->sphb, pdev);

    offset = spapr_create_pci_child_dt(p->sphb, pdev,

                                       drc_index, NULL,

                                       p->fdt, p->node_off);

    if (!offset) {

        error_report("Failed to create pci child device tree node");

        return;

    }

    if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) !=

         PCI_HEADER_TYPE_BRIDGE)) {

        return;

    }

    sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));

    if (!sec_bus) {

        return;

    }

    s_fdt.fdt = p->fdt;

    s_fdt.node_off = offset;

    s_fdt.sphb = p->sphb;

    pci_for_each_device(sec_bus, pci_bus_num(sec_bus),

                        spapr_populate_pci_devices_dt,

                        &s_fdt);

}


static void fifo_trigger_update(void *opaque)

{

    CadenceUARTState *s = opaque;

    s->r[R_CISR] |= UART_INTR_TIMEOUT;

    uart_update_status(s);

}


const char *qemu_get_version(void)

{

    return qemu_version;

}


static int v9fs_synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)

{

    errno = ENOSYS;

    return -1;

}


int pit_get_mode(PITState *pit, int channel)

{

    PITChannelState *s = &pit->channels[channel];

    return s->mode;

}


START_TEST(unterminated_sq_string)

{

    QObject *obj = qobject_from_json("'abc");

    fail_unless(obj == NULL);

}


static void release_drive(Object *obj, const char *name, void *opaque)

{

    DeviceState *dev = DEVICE(obj);

    Property *prop = opaque;

    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);

    if (*ptr) {

        bdrv_detach_dev(*ptr, dev);

        blockdev_auto_del(*ptr);

    }

}


size_t av_cpu_max_align(void)

{

    int flags = av_get_cpu_flags();

    if (flags & AV_CPU_FLAG_AVX)

        return 32;

    if (flags & (AV_CPU_FLAG_ALTIVEC | AV_CPU_FLAG_SSE | AV_CPU_FLAG_NEON))

        return 16;

    return 8;

}


void store_booke_tsr (CPUState *env, target_ulong val)

{

    LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);

    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);

    if (val & 0x80000000)

        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);

}


static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,

                              char *buf, size_t bufsz)

{

    ssize_t tsize = -1;

    char buffer[PATH_MAX];

    char *path = fs_path->data;

    if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||

        (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {

        int fd;

        fd = open(rpath(fs_ctx, path, buffer), O_RDONLY | O_NOFOLLOW);

        if (fd == -1) {

            return -1;

        }

        do {

            tsize = read(fd, (void *)buf, bufsz);

        } while (tsize == -1 && errno == EINTR);

        close(fd);

        return tsize;

    } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||

               (fs_ctx->export_flags & V9FS_SM_NONE)) {

        tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);

    }

    return tsize;

}


static void pc_dimm_unplug(HotplugHandler *hotplug_dev,

                           DeviceState *dev, Error **errp)

{

    PCMachineState *pcms = PC_MACHINE(hotplug_dev);

    PCDIMMDevice *dimm = PC_DIMM(dev);

    PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);

    MemoryRegion *mr = ddc->get_memory_region(dimm);

    HotplugHandlerClass *hhc;

    Error *local_err = NULL;

    if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {

        error_setg(&local_err,

                   "nvdimm device hot unplug is not supported yet.");

        goto out;

    }

    hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);

    hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);

    if (local_err) {

        goto out;

    }

    pc_dimm_memory_unplug(dev, &pcms->hotplug_memory, mr);

    object_unparent(OBJECT(dev));

 out:

    error_propagate(errp, local_err);

}


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

{

    pflash_t *pfl = CFI_PFLASH02(dev);

    uint32_t chip_len;

    int ret;

    Error *local_err = NULL;

    chip_len = pfl->sector_len * pfl->nb_blocs;

    /* XXX: to be fixed */

#if 0

    if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&

        total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))

        return NULL;

#endif

    memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ?

                                  &pflash_cfi02_ops_be : &pflash_cfi02_ops_le,

                                  pfl, pfl->name, chip_len, &local_err);

    if (local_err) {

        error_propagate(errp, local_err);

        return;

    }

    vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl));

    pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);

    pfl->chip_len = chip_len;

    if (pfl->bs) {

        /* read the initial flash content */

        ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);

        if (ret < 0) {

            vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl));

            error_setg(errp, "failed to read the initial flash content");

            return;

        }

    }

    pflash_setup_mappings(pfl);

    pfl->rom_mode = 1;

    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);

    if (pfl->bs) {

        pfl->ro = bdrv_is_read_only(pfl->bs);

    } else {

        pfl->ro = 0;

    }

    pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);

    pfl->wcycle = 0;

    pfl->cmd = 0;

    pfl->status = 0;

    /* Hardcoded CFI table (mostly from SG29 Spansion flash) */

    pfl->cfi_len = 0x52;

    /* Standard "QRY" string */

    pfl->cfi_table[0x10] = 'Q';

    pfl->cfi_table[0x11] = 'R';

    pfl->cfi_table[0x12] = 'Y';

    /* Command set (AMD/Fujitsu) */

    pfl->cfi_table[0x13] = 0x02;

    pfl->cfi_table[0x14] = 0x00;

    /* Primary extended table address */

    pfl->cfi_table[0x15] = 0x31;

    pfl->cfi_table[0x16] = 0x00;

    /* Alternate command set (none) */

    pfl->cfi_table[0x17] = 0x00;

    pfl->cfi_table[0x18] = 0x00;

    /* Alternate extended table (none) */

    pfl->cfi_table[0x19] = 0x00;

    pfl->cfi_table[0x1A] = 0x00;

    /* Vcc min */

    pfl->cfi_table[0x1B] = 0x27;

    /* Vcc max */

    pfl->cfi_table[0x1C] = 0x36;

    /* Vpp min (no Vpp pin) */

    pfl->cfi_table[0x1D] = 0x00;

    /* Vpp max (no Vpp pin) */

    pfl->cfi_table[0x1E] = 0x00;

    /* Reserved */

    pfl->cfi_table[0x1F] = 0x07;

    /* Timeout for min size buffer write (NA) */

    pfl->cfi_table[0x20] = 0x00;

    /* Typical timeout for block erase (512 ms) */

    pfl->cfi_table[0x21] = 0x09;

    /* Typical timeout for full chip erase (4096 ms) */

    pfl->cfi_table[0x22] = 0x0C;

    /* Reserved */

    pfl->cfi_table[0x23] = 0x01;

    /* Max timeout for buffer write (NA) */

    pfl->cfi_table[0x24] = 0x00;

    /* Max timeout for block erase */

    pfl->cfi_table[0x25] = 0x0A;

    /* Max timeout for chip erase */

    pfl->cfi_table[0x26] = 0x0D;

    /* Device size */

    pfl->cfi_table[0x27] = ctz32(chip_len);

    /* Flash device interface (8 & 16 bits) */

    pfl->cfi_table[0x28] = 0x02;

    pfl->cfi_table[0x29] = 0x00;

    /* Max number of bytes in multi-bytes write */

    /* XXX: disable buffered write as it's not supported */

    //    pfl->cfi_table[0x2A] = 0x05;

    pfl->cfi_table[0x2A] = 0x00;

    pfl->cfi_table[0x2B] = 0x00;

    /* Number of erase block regions (uniform) */

    pfl->cfi_table[0x2C] = 0x01;

    /* Erase block region 1 */

    pfl->cfi_table[0x2D] = pfl->nb_blocs - 1;

    pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8;

    pfl->cfi_table[0x2F] = pfl->sector_len >> 8;

    pfl->cfi_table[0x30] = pfl->sector_len >> 16;

    /* Extended */

    pfl->cfi_table[0x31] = 'P';

    pfl->cfi_table[0x32] = 'R';

    pfl->cfi_table[0x33] = 'I';

    pfl->cfi_table[0x34] = '1';

    pfl->cfi_table[0x35] = '0';

    pfl->cfi_table[0x36] = 0x00;

    pfl->cfi_table[0x37] = 0x00;

    pfl->cfi_table[0x38] = 0x00;

    pfl->cfi_table[0x39] = 0x00;

    pfl->cfi_table[0x3a] = 0x00;

    pfl->cfi_table[0x3b] = 0x00;

    pfl->cfi_table[0x3c] = 0x00;

}


static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,

                                     TCGv arg2, int sign, int compute_ov)

{

    TCGLabel *l1 = gen_new_label();

    TCGLabel *l2 = gen_new_label();

    TCGv_i32 t0 = tcg_temp_local_new_i32();

    TCGv_i32 t1 = tcg_temp_local_new_i32();

    tcg_gen_trunc_tl_i32(t0, arg1);

    tcg_gen_trunc_tl_i32(t1, arg2);

    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);

    if (sign) {

        TCGLabel *l3 = gen_new_label();

        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);

        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);

        gen_set_label(l3);

        tcg_gen_div_i32(t0, t0, t1);

    } else {

        tcg_gen_divu_i32(t0, t0, t1);

    }

    if (compute_ov) {

        tcg_gen_movi_tl(cpu_ov, 0);

    }

    tcg_gen_br(l2);

    gen_set_label(l1);

    if (sign) {

        tcg_gen_sari_i32(t0, t0, 31);

    } else {

        tcg_gen_movi_i32(t0, 0);

    }

    if (compute_ov) {

        tcg_gen_movi_tl(cpu_ov, 1);

        tcg_gen_movi_tl(cpu_so, 1);

    }

    gen_set_label(l2);

    tcg_gen_extu_i32_tl(ret, t0);

    tcg_temp_free_i32(t0);

    tcg_temp_free_i32(t1);

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

        gen_set_Rc0(ctx, ret);

}


static void omap_prcm_apll_update(struct omap_prcm_s *s)

{

    int mode[2];

    mode[0] = (s->clken[9] >> 6) & 3;

    s->apll_lock[0] = (mode[0] == 3);

    mode[1] = (s->clken[9] >> 2) & 3;

    s->apll_lock[1] = (mode[1] == 3);

    /* TODO: update clocks */

    if (mode[0] == 1 || mode[0] == 2 || mode[1] == 1 || mode[1] == 2)

        fprintf(stderr, "%s: bad EN_54M_PLL or bad EN_96M_PLL\n",

                        __FUNCTION__);

}


static uint64_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset,

                                   unsigned size)

{

    musicpal_gpio_state *s = opaque;

    switch (offset) {

    case MP_GPIO_OE_HI: /* used for LCD brightness control */

        return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;

    case MP_GPIO_OUT_LO:

        return s->out_state & 0xFFFF;

    case MP_GPIO_OUT_HI:

        return s->out_state >> 16;

    case MP_GPIO_IN_LO:

        return s->in_state & 0xFFFF;

    case MP_GPIO_IN_HI:

        return s->in_state >> 16;

    case MP_GPIO_IER_LO:

        return s->ier & 0xFFFF;

    case MP_GPIO_IER_HI:

        return s->ier >> 16;

    case MP_GPIO_IMR_LO:

        return s->imr & 0xFFFF;

    case MP_GPIO_IMR_HI:

        return s->imr >> 16;

    case MP_GPIO_ISR_LO:

        return s->isr & 0xFFFF;

    case MP_GPIO_ISR_HI:

        return s->isr >> 16;

    default:

        return 0;

    }

}


static void test_sanity(void)

{

    AHCIQState *ahci;

    ahci = ahci_boot();

    ahci_shutdown(ahci);

}


static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)

{

    char *backing_file = NULL;

    char *backing_fmt = NULL;

    char *buf = NULL;

    uint64_t size = 0;

    int flags = 0;

    size_t cluster_size = DEFAULT_CLUSTER_SIZE;

    PreallocMode prealloc;

    int version = 3;

    uint64_t refcount_bits = 16;

    int refcount_order;

    Error *local_err = NULL;

    int ret;

    /* Read out options */

    size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),

                    BDRV_SECTOR_SIZE);

    backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);

    backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);

    if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {

        flags |= BLOCK_FLAG_ENCRYPT;

    }

    cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,

                                         DEFAULT_CLUSTER_SIZE);

    buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);

    prealloc = qapi_enum_parse(PreallocMode_lookup, buf,

                               PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,

                               &local_err);

    if (local_err) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto finish;

    }

    g_free(buf);

    buf = qemu_opt_get_del(opts, BLOCK_OPT_COMPAT_LEVEL);

    if (!buf) {

        /* keep the default */

    } else if (!strcmp(buf, "0.10")) {

        version = 2;

    } else if (!strcmp(buf, "1.1")) {

        version = 3;

    } else {

        error_setg(errp, "Invalid compatibility level: '%s'", buf);

        ret = -EINVAL;

        goto finish;

    }

    if (qemu_opt_get_bool_del(opts, BLOCK_OPT_LAZY_REFCOUNTS, false)) {

        flags |= BLOCK_FLAG_LAZY_REFCOUNTS;

    }

    if (backing_file && prealloc != PREALLOC_MODE_OFF) {

        error_setg(errp, "Backing file and preallocation cannot be used at "

                   "the same time");

        ret = -EINVAL;

        goto finish;

    }

    if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) {

        error_setg(errp, "Lazy refcounts only supported with compatibility "

                   "level 1.1 and above (use compat=1.1 or greater)");

        ret = -EINVAL;

        goto finish;

    }

    refcount_bits = qemu_opt_get_number_del(opts, BLOCK_OPT_REFCOUNT_BITS,

                                            refcount_bits);

    if (refcount_bits > 64 || !is_power_of_2(refcount_bits)) {

        error_setg(errp, "Refcount width must be a power of two and may not "

                   "exceed 64 bits");

        ret = -EINVAL;

        goto finish;

    }

    if (version < 3 && refcount_bits != 16) {

        error_setg(errp, "Different refcount widths than 16 bits require "

                   "compatibility level 1.1 or above (use compat=1.1 or "

                   "greater)");

        ret = -EINVAL;

        goto finish;

    }

    refcount_order = ctz32(refcount_bits);

    ret = qcow2_create2(filename, size, backing_file, backing_fmt, flags,

                        cluster_size, prealloc, opts, version, refcount_order,

                        &local_err);

    if (local_err) {

        error_propagate(errp, local_err);

    }

finish:

    g_free(backing_file);

    g_free(backing_fmt);

    g_free(buf);

    return ret;

}


static void h261_loop_filter_c(uint8_t *src, int stride){

    int x,y,xy,yz;

    int temp[64];

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

        temp[x      ] = 4*src[x           ];

        temp[x + 7*8] = 4*src[x + 7*stride];

    }

    for(y=1; y<7; y++){

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

            xy = y * stride + x;

            yz = y * 8 + x;

            temp[yz] = src[xy - stride] + 2*src[xy] + src[xy + stride];

        }

    }

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

        src[  y*stride] = (temp[  y*8] + 2)>>2;

        src[7+y*stride] = (temp[7+y*8] + 2)>>2;

        for(x=1; x<7; x++){

            xy = y * stride + x;

            yz = y * 8 + x;

            src[xy] = (temp[yz-1] + 2*temp[yz] + temp[yz+1] + 8)>>4;

        }

    }

}


int ff_rtsp_connect(AVFormatContext *s)

{

    RTSPState *rt = s->priv_data;

    char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128];

    char *option_list, *option, *filename;

    int port, err, tcp_fd;

    RTSPMessageHeader reply1 = {}, *reply = &reply1;

    int lower_transport_mask = 0;

    char real_challenge[64];

    struct sockaddr_storage peer;

    socklen_t peer_len = sizeof(peer);

    if (!ff_network_init())

        return AVERROR(EIO);

redirect:

    rt->control_transport = RTSP_MODE_PLAIN;

    /* extract hostname and port */

    av_url_split(NULL, 0, auth, sizeof(auth),

                 host, sizeof(host), &port, path, sizeof(path), s->filename);

    if (*auth) {

        av_strlcpy(rt->auth, auth, sizeof(rt->auth));

    }

    if (port < 0)

        port = RTSP_DEFAULT_PORT;

    /* search for options */

    option_list = strrchr(path, '?');

    if (option_list) {

        /* Strip out the RTSP specific options, write out the rest of

         * the options back into the same string. */

        filename = option_list;

        while (option_list) {

            /* move the option pointer */

            option = ++option_list;

            option_list = strchr(option_list, '&');

            if (option_list)

                *option_list = 0;

            /* handle the options */

            if (!strcmp(option, "udp")) {

                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP);

            } else if (!strcmp(option, "multicast")) {

                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_UDP_MULTICAST);

            } else if (!strcmp(option, "tcp")) {

                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);

            } else if(!strcmp(option, "http")) {

                lower_transport_mask |= (1<< RTSP_LOWER_TRANSPORT_TCP);

                rt->control_transport = RTSP_MODE_TUNNEL;

            } else {

                /* Write options back into the buffer, using memmove instead

                 * of strcpy since the strings may overlap. */

                int len = strlen(option);

                memmove(++filename, option, len);

                filename += len;

                if (option_list) *filename = '&';

            }

        }

        *filename = 0;

    }

    if (!lower_transport_mask)

        lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1;

    if (s->oformat) {

        /* Only UDP or TCP - UDP multicast isn't supported. */

        lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_UDP) |

                                (1 << RTSP_LOWER_TRANSPORT_TCP);

        if (!lower_transport_mask || rt->control_transport == RTSP_MODE_TUNNEL) {

            av_log(s, AV_LOG_ERROR, "Unsupported lower transport method, "

                                    "only UDP and TCP are supported for output.\n");

            err = AVERROR(EINVAL);

            goto fail;

        }

    }

    /* Construct the URI used in request; this is similar to s->filename,

     * but with authentication credentials removed and RTSP specific options

     * stripped out. */

    ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL,

                host, port, "%s", path);

    if (rt->control_transport == RTSP_MODE_TUNNEL) {

        /* set up initial handshake for tunneling */

        char httpname[1024];

        char sessioncookie[17];

        char headers[1024];

        ff_url_join(httpname, sizeof(httpname), "http", auth, host, port, "%s", path);

        snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",

                 av_get_random_seed(), av_get_random_seed());

        /* GET requests */

        if (url_alloc(&rt->rtsp_hd, httpname, URL_RDONLY) < 0) {

            err = AVERROR(EIO);

            goto fail;

        }

        /* generate GET headers */

        snprintf(headers, sizeof(headers),

                 "x-sessioncookie: %s\r\n"

                 "Accept: application/x-rtsp-tunnelled\r\n"

                 "Pragma: no-cache\r\n"

                 "Cache-Control: no-cache\r\n",

                 sessioncookie);

        ff_http_set_headers(rt->rtsp_hd, headers);

        /* complete the connection */

        if (url_connect(rt->rtsp_hd)) {

            err = AVERROR(EIO);

            goto fail;

        }

        /* POST requests */

        if (url_alloc(&rt->rtsp_hd_out, httpname, URL_WRONLY) < 0 ) {

            err = AVERROR(EIO);

            goto fail;

        }

        /* generate POST headers */

        snprintf(headers, sizeof(headers),

                 "x-sessioncookie: %s\r\n"

                 "Content-Type: application/x-rtsp-tunnelled\r\n"

                 "Pragma: no-cache\r\n"

                 "Cache-Control: no-cache\r\n"

                 "Content-Length: 32767\r\n"

                 "Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n",

                 sessioncookie);

        ff_http_set_headers(rt->rtsp_hd_out, headers);

        ff_http_set_chunked_transfer_encoding(rt->rtsp_hd_out, 0);

        /* Initialize the authentication state for the POST session. The HTTP

         * protocol implementation doesn't properly handle multi-pass

         * authentication for POST requests, since it would require one of

         * the following:

         * - implementing Expect: 100-continue, which many HTTP servers

         *   don't support anyway, even less the RTSP servers that do HTTP

         *   tunneling

         * - sending the whole POST data until getting a 401 reply specifying

         *   what authentication method to use, then resending all that data

         * - waiting for potential 401 replies directly after sending the

         *   POST header (waiting for some unspecified time)

         * Therefore, we copy the full auth state, which works for both basic

         * and digest. (For digest, we would have to synchronize the nonce

         * count variable between the two sessions, if we'd do more requests

         * with the original session, though.)

         */

        ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd);

        /* complete the connection */

        if (url_connect(rt->rtsp_hd_out)) {

            err = AVERROR(EIO);

            goto fail;

        }

    } else {

        /* open the tcp connection */

        ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);

        if (url_open(&rt->rtsp_hd, tcpname, URL_RDWR) < 0) {

            err = AVERROR(EIO);

            goto fail;

        }

        rt->rtsp_hd_out = rt->rtsp_hd;

    }

    rt->seq = 0;

    tcp_fd = url_get_file_handle(rt->rtsp_hd);

    if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) {

        getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host),

                    NULL, 0, NI_NUMERICHOST);

    }

    /* request options supported by the server; this also detects server

     * type */

    for (rt->server_type = RTSP_SERVER_RTP;;) {

        cmd[0] = 0;

        if (rt->server_type == RTSP_SERVER_REAL)

            av_strlcat(cmd,

                       /**

                        * The following entries are required for proper

                        * streaming from a Realmedia server. They are

                        * interdependent in some way although we currently

                        * don't quite understand how. Values were copied

                        * from mplayer SVN r23589.

                        * @param CompanyID is a 16-byte ID in base64

                        * @param ClientChallenge is a 16-byte ID in hex

                        */

                       "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7\r\n"

                       "PlayerStarttime: [28/03/2003:22:50:23 00:00]\r\n"

                       "CompanyID: KnKV4M4I/B2FjJ1TToLycw==\r\n"

                       "GUID: 00000000-0000-0000-0000-000000000000\r\n",

                       sizeof(cmd));

        ff_rtsp_send_cmd(s, "OPTIONS", rt->control_uri, cmd, reply, NULL);

        if (reply->status_code != RTSP_STATUS_OK) {

            err = AVERROR_INVALIDDATA;

            goto fail;

        }

        /* detect server type if not standard-compliant RTP */

        if (rt->server_type != RTSP_SERVER_REAL && reply->real_challenge[0]) {

            rt->server_type = RTSP_SERVER_REAL;

            continue;

        } else if (!strncasecmp(reply->server, "WMServer/", 9)) {

            rt->server_type = RTSP_SERVER_WMS;

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

            strcpy(real_challenge, reply->real_challenge);

        break;

    }

    if (s->iformat)

        err = rtsp_setup_input_streams(s, reply);

    else

        err = rtsp_setup_output_streams(s, host);

    if (err)

        goto fail;

    do {

        int lower_transport = ff_log2_tab[lower_transport_mask &

                                  ~(lower_transport_mask - 1)];

        err = make_setup_request(s, host, port, lower_transport,

                                 rt->server_type == RTSP_SERVER_REAL ?

                                     real_challenge : NULL);

        if (err < 0)

            goto fail;

        lower_transport_mask &= ~(1 << lower_transport);

        if (lower_transport_mask == 0 && err == 1) {

            err = FF_NETERROR(EPROTONOSUPPORT);

            goto fail;

        }

    } while (err);

    rt->state = RTSP_STATE_IDLE;

    rt->seek_timestamp = 0; /* default is to start stream at position zero */

    return 0;

 fail:

    ff_rtsp_close_streams(s);

    ff_rtsp_close_connections(s);

    if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) {

        av_strlcpy(s->filename, reply->location, sizeof(s->filename));

        av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n",

               reply->status_code,

               s->filename);

        goto redirect;

    }

    ff_network_close();

    return err;

}


static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,

                            Error **errp)

{

    BlockInfo *info = g_malloc0(sizeof(*info));

    BlockDriverState *bs = blk_bs(blk);

    BlockDriverState *bs0;

    ImageInfo **p_image_info;

    Error *local_err = NULL;

    info->device = g_strdup(blk_name(blk));

    info->type = g_strdup("unknown");

    info->locked = blk_dev_is_medium_locked(blk);

    info->removable = blk_dev_has_removable_media(blk);

    if (blk_dev_has_removable_media(blk)) {

        info->has_tray_open = true;

        info->tray_open = blk_dev_is_tray_open(blk);

    }

    if (bdrv_iostatus_is_enabled(bs)) {

        info->has_io_status = true;

        info->io_status = bs->iostatus;

    }

    if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {

        info->has_dirty_bitmaps = true;

        info->dirty_bitmaps = bdrv_query_dirty_bitmaps(bs);

    }

    if (bs->drv) {

        info->has_inserted = true;

        info->inserted = bdrv_block_device_info(bs);

        bs0 = bs;

        p_image_info = &info->inserted->image;

        while (1) {

            bdrv_query_image_info(bs0, p_image_info, &local_err);

            if (local_err) {

                error_propagate(errp, local_err);

                goto err;

            }

            if (bs0->drv && bs0->backing_hd) {

                bs0 = bs0->backing_hd;

                (*p_image_info)->has_backing_image = true;

                p_image_info = &((*p_image_info)->backing_image);

            } else {

                break;

            }

        }

    }

    *p_info = info;

    return;

 err:

    qapi_free_BlockInfo(info);

}