static Aml *build_crs(PCIHostState *host,

                      GPtrArray *io_ranges, GPtrArray *mem_ranges)

{

    Aml *crs = aml_resource_template();

    uint8_t max_bus = pci_bus_num(host->bus);

    uint8_t type;

    int devfn;

    for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {

        int i;

        uint64_t range_base, range_limit;

        PCIDevice *dev = host->bus->devices[devfn];

        if (!dev) {

            continue;

        }

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

            PCIIORegion *r = &dev->io_regions[i];

            range_base = r->addr;

            range_limit = r->addr + r->size - 1;

            /*

             * Work-around for old bioses

             * that do not support multiple root buses

             */

            if (!range_base || range_base > range_limit) {

                continue;

            }

            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {

                aml_append(crs,

                    aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,

                                AML_POS_DECODE, AML_ENTIRE_RANGE,

                                0,

                                range_base,

                                range_limit,

                                0,

                                range_limit - range_base + 1));

                crs_range_insert(io_ranges, range_base, range_limit);

            } else { /* "memory" */

                aml_append(crs,

                    aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,

                                     AML_MAX_FIXED, AML_NON_CACHEABLE,

                                     AML_READ_WRITE,

                                     0,

                                     range_base,

                                     range_limit,

                                     0,

                                     range_limit - range_base + 1));

                crs_range_insert(mem_ranges, range_base, range_limit);

            }

        }

        type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;

        if (type == PCI_HEADER_TYPE_BRIDGE) {

            uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];

            if (subordinate > max_bus) {

                max_bus = subordinate;

            }

            range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);

            range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);

            /*

             * Work-around for old bioses

             * that do not support multiple root buses

             */

            if (range_base || range_base > range_limit) {

                aml_append(crs,

                           aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,

                                       AML_POS_DECODE, AML_ENTIRE_RANGE,

                                       0,

                                       range_base,

                                       range_limit,

                                       0,

                                       range_limit - range_base + 1));

                crs_range_insert(io_ranges, range_base, range_limit);

            }

            range_base =

                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);

            range_limit =

                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);

            /*

             * Work-around for old bioses

             * that do not support multiple root buses

             */

            if (range_base || range_base > range_limit) {

                aml_append(crs,

                           aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,

                                            AML_MAX_FIXED, AML_NON_CACHEABLE,

                                            AML_READ_WRITE,

                                            0,

                                            range_base,

                                            range_limit,

                                            0,

                                            range_limit - range_base + 1));

                crs_range_insert(mem_ranges, range_base, range_limit);

          }

            range_base =

                pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);

            range_limit =

                pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);

            /*

             * Work-around for old bioses

             * that do not support multiple root buses

             */

            if (range_base || range_base > range_limit) {

                aml_append(crs,

                           aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,

                                            AML_MAX_FIXED, AML_NON_CACHEABLE,

                                            AML_READ_WRITE,

                                            0,

                                            range_base,

                                            range_limit,

                                            0,

                                            range_limit - range_base + 1));

                crs_range_insert(mem_ranges, range_base, range_limit);

            }

        }

    }

    aml_append(crs,

        aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,

                            0,

                            pci_bus_num(host->bus),

                            max_bus,

                            0,

                            max_bus - pci_bus_num(host->bus) + 1));

    return crs;

}


static int escc_init1(SysBusDevice *dev)

{

    ESCCState *s = ESCC(dev);

    unsigned int i;

    s->chn[0].disabled = s->disabled;

    s->chn[1].disabled = s->disabled;

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

        sysbus_init_irq(dev, &s->chn[i].irq);

        s->chn[i].chn = 1 - i;

        s->chn[i].clock = s->frequency / 2;

        if (s->chn[i].chr) {

            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,

                                  serial_receive1, serial_event, &s->chn[i]);

        }

    }

    s->chn[0].otherchn = &s->chn[1];

    s->chn[1].otherchn = &s->chn[0];

    memory_region_init_io(&s->mmio, OBJECT(s), &escc_mem_ops, s, "escc",

                          ESCC_SIZE << s->it_shift);

    sysbus_init_mmio(dev, &s->mmio);

    if (s->chn[0].type == mouse) {

        qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,

                                     "QEMU Sun Mouse");

    }

    if (s->chn[1].type == kbd) {

        qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);

    }

    return 0;

}


void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout)

{

    QEMUBH *bh;

    for (bh = ctx->first_bh; bh; bh = bh->next) {

        if (!bh->deleted && bh->scheduled) {

            if (bh->idle) {

                /* idle bottom halves will be polled at least

                 * every 10ms */

                *timeout = MIN(10, *timeout);

            } else {

                /* non-idle bottom halves will be executed

                 * immediately */

                *timeout = 0;

                break;

            }

        }

    }

}


void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f,

                                   ImageInfoSpecific *info_spec)

{

    QObject *obj, *data;

    Visitor *v = qobject_output_visitor_new(&obj);

    visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);

    visit_complete(v, &obj);

    assert(qobject_type(obj) == QTYPE_QDICT);

    data = qdict_get(qobject_to_qdict(obj), "data");

    dump_qobject(func_fprintf, f, 1, data);

    qobject_decref(obj);

    visit_free(v);

}


static mfxIMPL choose_implementation(const InputStream *ist)

{

    static const struct {

        const char *name;

        mfxIMPL     impl;

    } impl_map[] = {

        { "auto",     MFX_IMPL_AUTO         },

        { "sw",       MFX_IMPL_SOFTWARE     },

        { "hw",       MFX_IMPL_HARDWARE     },

        { "auto_any", MFX_IMPL_AUTO_ANY     },

        { "hw_any",   MFX_IMPL_HARDWARE_ANY },

        { "hw2",      MFX_IMPL_HARDWARE2    },

        { "hw3",      MFX_IMPL_HARDWARE3    },

        { "hw4",      MFX_IMPL_HARDWARE4    },

    };

    mfxIMPL impl = MFX_IMPL_AUTO_ANY;

    int i;

    if (ist->hwaccel_device) {

        for (i = 0; i < FF_ARRAY_ELEMS(impl_map); i++)

            if (!strcmp(ist->hwaccel_device, impl_map[i].name)) {

                impl = impl_map[i].impl;

                break;

            }

        if (i == FF_ARRAY_ELEMS(impl_map))

            impl = strtol(ist->hwaccel_device, NULL, 0);

    }

    return impl;

}


SocketAddress *socket_address_crumple(SocketAddressFlat *addr_flat)

{

    SocketAddress *addr = g_new(SocketAddress, 1);

    switch (addr_flat->type) {

    case SOCKET_ADDRESS_FLAT_TYPE_INET:

        addr->type = SOCKET_ADDRESS_KIND_INET;

        addr->u.inet.data = QAPI_CLONE(InetSocketAddress,

                                       &addr_flat->u.inet);

        break;

    case SOCKET_ADDRESS_FLAT_TYPE_UNIX:

        addr->type = SOCKET_ADDRESS_KIND_UNIX;

        addr->u.q_unix.data = QAPI_CLONE(UnixSocketAddress,

                                         &addr_flat->u.q_unix);

        break;

    case SOCKET_ADDRESS_FLAT_TYPE_VSOCK:

        addr->type = SOCKET_ADDRESS_KIND_VSOCK;

        addr->u.vsock.data = QAPI_CLONE(VsockSocketAddress,

                                        &addr_flat->u.vsock);

        break;

    case SOCKET_ADDRESS_FLAT_TYPE_FD:

        addr->type = SOCKET_ADDRESS_KIND_FD;

        addr->u.fd.data = QAPI_CLONE(String, &addr_flat->u.fd);

        break;

    default:

        abort();

    }

    return addr;

}


void aio_set_event_notifier(AioContext *ctx,

                            EventNotifier *e,

                            EventNotifierHandler *io_notify)

{

    AioHandler *node;

    QLIST_FOREACH(node, &ctx->aio_handlers, node) {

        if (node->e == e && !node->deleted) {

            break;

        }

    }

    /* Are we deleting the fd handler? */

    if (!io_notify) {

        if (node) {

            g_source_remove_poll(&ctx->source, &node->pfd);

            /* If the lock is held, just mark the node as deleted */

            if (ctx->walking_handlers) {

                node->deleted = 1;

                node->pfd.revents = 0;

            } else {

                /* Otherwise, delete it for real.  We can't just mark it as

                 * deleted because deleted nodes are only cleaned up after

                 * releasing the walking_handlers lock.

                 */

                QLIST_REMOVE(node, node);

                g_free(node);

            }

        }

    } else {

        if (node == NULL) {

            /* Alloc and insert if it's not already there */

            node = g_malloc0(sizeof(AioHandler));

            node->e = e;

            node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);

            node->pfd.events = G_IO_IN;

            QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);

            g_source_add_poll(&ctx->source, &node->pfd);

        }

        /* Update handler with latest information */

        node->io_notify = io_notify;

    }

    aio_notify(ctx);

}


static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)

{

    uint32_t int_mask = 0;

    uint32_t plink = td->link;

    uint32_t token = uhci_queue_token(td);

    UHCI_TD ptd;

    int ret;

    while (is_valid(plink)) {

        pci_dma_read(&s->dev, plink & ~0xf, &ptd, sizeof(ptd));

        le32_to_cpus(&ptd.link);

        le32_to_cpus(&ptd.ctrl);

        le32_to_cpus(&ptd.token);

        le32_to_cpus(&ptd.buffer);

        if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {

            break;

        }

        if (uhci_queue_token(&ptd) != token) {

            break;

        }

        trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);

        ret = uhci_handle_td(s, plink, &ptd, &int_mask, true);

        if (ret == TD_RESULT_ASYNC_CONT) {

            break;

        }

        assert(ret == TD_RESULT_ASYNC_START);

        assert(int_mask == 0);

        if (ptd.ctrl & TD_CTRL_SPD) {

            break;

        }

        plink = ptd.link;

    }

}


static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,

                              target_ulong eaddr, int rw, int type)

{

    hwaddr hash;

    target_ulong vsid;

    int ds, pr, target_page_bits;

    int ret, ret2;

    pr = msr_pr;

    ctx->eaddr = eaddr;

#if defined(TARGET_PPC64)

    if (env->mmu_model & POWERPC_MMU_64) {

        ppc_slb_t *slb;

        target_ulong pageaddr;

        int segment_bits;

        LOG_MMU("Check SLBs\n");

        slb = slb_lookup(env, eaddr);

        if (!slb) {

            return -5;

        }

        if (slb->vsid & SLB_VSID_B) {

            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;

            segment_bits = 40;

        } else {

            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;

            segment_bits = 28;

        }

        target_page_bits = (slb->vsid & SLB_VSID_L)

            ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;

        ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)

                      : (slb->vsid & SLB_VSID_KS));

        ds = 0;

        ctx->nx = !!(slb->vsid & SLB_VSID_N);

        pageaddr = eaddr & ((1ULL << segment_bits)

                            - (1ULL << target_page_bits));

        if (slb->vsid & SLB_VSID_B) {

            hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);

        } else {

            hash = vsid ^ (pageaddr >> target_page_bits);

        }

        /* Only 5 bits of the page index are used in the AVPN */

        ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |

            ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));

    } else

#endif /* defined(TARGET_PPC64) */

    {

        target_ulong sr, pgidx;

        sr = env->sr[eaddr >> 28];

        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||

                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;

        ds = sr & 0x80000000 ? 1 : 0;

        ctx->nx = sr & 0x10000000 ? 1 : 0;

        vsid = sr & 0x00FFFFFF;

        target_page_bits = TARGET_PAGE_BITS;

        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="

                TARGET_FMT_lx " lr=" TARGET_FMT_lx

                " ir=%d dr=%d pr=%d %d t=%d\n",

                eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,

                (int)msr_dr, pr != 0 ? 1 : 0, rw, type);

        pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;

        hash = vsid ^ pgidx;

        ctx->ptem = (vsid << 7) | (pgidx >> 10);

    }

    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",

            ctx->key, ds, ctx->nx, vsid);

    ret = -1;

    if (!ds) {

        /* Check if instruction fetch is allowed, if needed */

        if (type != ACCESS_CODE || ctx->nx == 0) {

            /* Page address translation */

            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx

                    " hash " TARGET_FMT_plx "\n",

                    env->htab_base, env->htab_mask, hash);

            ctx->hash[0] = hash;

            ctx->hash[1] = ~hash;

            /* Initialize real address with an invalid value */

            ctx->raddr = (hwaddr)-1ULL;

            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||

                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {

                /* Software TLB search */

                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);

            } else {

                LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx

                        " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx

                        " hash=" TARGET_FMT_plx "\n",

                        env->htab_base, env->htab_mask, vsid, ctx->ptem,

                        ctx->hash[0]);

                /* Primary table lookup */

                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);

                if (ret < 0) {

                    /* Secondary table lookup */

                    if (eaddr != 0xEFFFFFFF) {

                        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx

                                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx

                                " hash=" TARGET_FMT_plx "\n", env->htab_base,

                                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);

                    }

                    ret2 = find_pte(env, ctx, 1, rw, type,

                                    target_page_bits);

                    if (ret2 != -1) {

                        ret = ret2;

                    }

                }

            }

#if defined(DUMP_PAGE_TABLES)

            if (qemu_log_enabled()) {

                hwaddr curaddr;

                uint32_t a0, a1, a2, a3;

                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx

                         "\n", sdr, mask + 0x80);

                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);

                     curaddr += 16) {

                    a0 = ldl_phys(curaddr);

                    a1 = ldl_phys(curaddr + 4);

                    a2 = ldl_phys(curaddr + 8);

                    a3 = ldl_phys(curaddr + 12);

                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {

                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",

                                 curaddr, a0, a1, a2, a3);

                    }

                }

            }

#endif

        } else {

            LOG_MMU("No access allowed\n");

            ret = -3;

        }

    } else {

        target_ulong sr;

        LOG_MMU("direct store...\n");

        /* Direct-store segment : absolutely *BUGGY* for now */

        /* Direct-store implies a 32-bit MMU.

         * Check the Segment Register's bus unit ID (BUID).

         */

        sr = env->sr[eaddr >> 28];

        if ((sr & 0x1FF00000) >> 20 == 0x07f) {

            /* Memory-forced I/O controller interface access */

            /* If T=1 and BUID=x'07F', the 601 performs a memory access

             * to SR[28-31] LA[4-31], bypassing all protection mechanisms.

             */

            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);

            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;

            return 0;

        }

        switch (type) {

        case ACCESS_INT:

            /* Integer load/store : only access allowed */

            break;

        case ACCESS_CODE:

            /* No code fetch is allowed in direct-store areas */

            return -4;

        case ACCESS_FLOAT:

            /* Floating point load/store */

            return -4;

        case ACCESS_RES:

            /* lwarx, ldarx or srwcx. */

            return -4;

        case ACCESS_CACHE:

            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */

            /* Should make the instruction do no-op.

             * As it already do no-op, it's quite easy :-)

             */

            ctx->raddr = eaddr;

            return 0;

        case ACCESS_EXT:

            /* eciwx or ecowx */

            return -4;

        default:

            qemu_log("ERROR: instruction should not need "

                        "address translation\n");

            return -4;

        }

        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {

            ctx->raddr = eaddr;

            ret = 2;

        } else {

            ret = -2;

        }

    }

    return ret;

}


static void char_socket_test(void)

{

    Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait");

    Chardev *chr_client;

    QObject *addr;

    QDict *qdict, *data;

    const char *port;

    SocketIdleData d = { .chr = chr };

    CharBackend be;

    CharBackend client_be;

    char *tmp;

    d.be = &be;

    d.client_be = &be;

    g_assert_nonnull(chr);

    g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));

    addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);

    qdict = qobject_to_qdict(addr);

    data = qdict_get_qdict(qdict, "data");

    port = qdict_get_str(data, "port");

    tmp = g_strdup_printf("tcp:127.0.0.1:%s", port);

    QDECREF(qdict);

    qemu_chr_fe_init(&be, chr, &error_abort);

    qemu_chr_fe_set_handlers(&be, socket_can_read, socket_read,

                             NULL, &d, NULL, true);

    chr_client = qemu_chr_new("client", tmp);

    qemu_chr_fe_init(&client_be, chr_client, &error_abort);

    qemu_chr_fe_set_handlers(&client_be, socket_can_read_hello,

                             socket_read_hello,

                             NULL, &d, NULL, true);

    g_free(tmp);

    d.conn_expected = true;

    guint id = g_idle_add(char_socket_test_idle, &d);

    g_source_set_name_by_id(id, "test-idle");

    g_assert_cmpint(id, >, 0);

    main_loop();

    g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));

    g_assert(object_property_get_bool(OBJECT(chr_client),

                                      "connected", &error_abort));

    qemu_chr_write_all(chr_client, (const uint8_t *)"Z", 1);

    main_loop();

    object_unparent(OBJECT(chr_client));

    d.conn_expected = false;

    g_idle_add(char_socket_test_idle, &d);

    main_loop();

    object_unparent(OBJECT(chr));

}


void virtio_scsi_dataplane_start(VirtIOSCSI *s)

{

    int i;

    int rc;

    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));

    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);

    if (s->dataplane_started ||

        s->dataplane_starting ||

        s->dataplane_fenced ||

        s->ctx != iothread_get_aio_context(vs->conf.iothread)) {

        return;

    }

    s->dataplane_starting = true;

    /* Set up guest notifier (irq) */

    rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true);

    if (rc != 0) {

        fprintf(stderr, "virtio-scsi: Failed to set guest notifiers (%d), "

                "ensure -enable-kvm is set\n", rc);

        goto fail_guest_notifiers;

    }

    aio_context_acquire(s->ctx);

    rc = virtio_scsi_vring_init(s, vs->ctrl_vq, 0,

                                virtio_scsi_data_plane_handle_ctrl);

    if (rc) {

        goto fail_vrings;

    }

    rc = virtio_scsi_vring_init(s, vs->event_vq, 1,

                                virtio_scsi_data_plane_handle_event);

    if (rc) {

        goto fail_vrings;

    }

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

        rc = virtio_scsi_vring_init(s, vs->cmd_vqs[i], i + 2,

                                    virtio_scsi_data_plane_handle_cmd);

        if (rc) {

            goto fail_vrings;

        }

    }

    s->dataplane_starting = false;

    s->dataplane_started = true;

    aio_context_release(s->ctx);

    return;

fail_vrings:

    virtio_scsi_clear_aio(s);

    aio_context_release(s->ctx);

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

        virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);

    }

    k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false);

fail_guest_notifiers:

    s->dataplane_fenced = true;

    s->dataplane_starting = false;

    s->dataplane_started = true;

}


static void disas_fp_csel(DisasContext *s, uint32_t insn)

{

    unsigned int mos, type, rm, cond, rn, rd;

    int label_continue = -1;

    mos = extract32(insn, 29, 3);

    type = extract32(insn, 22, 2); /* 0 = single, 1 = double */

    rm = extract32(insn, 16, 5);

    cond = extract32(insn, 12, 4);

    rn = extract32(insn, 5, 5);

    rd = extract32(insn, 0, 5);

    if (mos || type > 1) {

        unallocated_encoding(s);

        return;

    }

    if (!fp_access_check(s)) {

        return;

    }

    if (cond < 0x0e) { /* not always */

        int label_match = gen_new_label();

        label_continue = gen_new_label();

        arm_gen_test_cc(cond, label_match);

        /* nomatch: */

        gen_mov_fp2fp(s, type, rd, rm);

        tcg_gen_br(label_continue);

        gen_set_label(label_match);

    }

    gen_mov_fp2fp(s, type, rd, rn);

    if (cond < 0x0e) { /* continue */

        gen_set_label(label_continue);

    }

}


int bdrv_open(BlockDriverState **pbs, const char *filename,

              const char *reference, QDict *options, int flags,

              BlockDriver *drv, Error **errp)

{

    int ret;

    BlockDriverState *file = NULL, *bs;

    const char *drvname;

    Error *local_err = NULL;

    int snapshot_flags = 0;

    assert(pbs);

    if (reference) {

        bool options_non_empty = options ? qdict_size(options) : false;

        QDECREF(options);

        if (*pbs) {

            error_setg(errp, "Cannot reuse an existing BDS when referencing "

                       "another block device");

            return -EINVAL;

        }

        if (filename || options_non_empty) {

            error_setg(errp, "Cannot reference an existing block device with "

                       "additional options or a new filename");

            return -EINVAL;

        }

        bs = bdrv_lookup_bs(reference, reference, errp);

        if (!bs) {

            return -ENODEV;

        }

        bdrv_ref(bs);

        *pbs = bs;

        return 0;

    }

    if (*pbs) {

        bs = *pbs;

    } else {

        bs = bdrv_new();

    }

    /* NULL means an empty set of options */

    if (options == NULL) {

        options = qdict_new();

    }

    ret = bdrv_fill_options(&options, &filename, flags, drv, &local_err);

    if (local_err) {

        goto fail;

    }

    /* Find the right image format driver */

    drv = NULL;

    drvname = qdict_get_try_str(options, "driver");

    if (drvname) {

        drv = bdrv_find_format(drvname);

        qdict_del(options, "driver");

        if (!drv) {

            error_setg(errp, "Unknown driver: '%s'", drvname);

            ret = -EINVAL;

            goto fail;

        }

    }

    assert(drvname || !(flags & BDRV_O_PROTOCOL));

    if (drv && !drv->bdrv_file_open) {

        /* If the user explicitly wants a format driver here, we'll need to add

         * another layer for the protocol in bs->file */

        flags &= ~BDRV_O_PROTOCOL;

    }

    bs->options = options;

    options = qdict_clone_shallow(options);

    /* Open image file without format layer */

    if ((flags & BDRV_O_PROTOCOL) == 0) {

        if (flags & BDRV_O_RDWR) {

            flags |= BDRV_O_ALLOW_RDWR;

        }

        if (flags & BDRV_O_SNAPSHOT) {

            snapshot_flags = bdrv_temp_snapshot_flags(flags);

            flags = bdrv_backing_flags(flags);

        }

        assert(file == NULL);

        ret = bdrv_open_image(&file, filename, options, "file",

                              bdrv_inherited_flags(flags),

                              true, &local_err);

        if (ret < 0) {

            goto fail;

        }

    }

    /* Image format probing */

    bs->probed = !drv;

    if (!drv && file) {

        ret = find_image_format(file, filename, &drv, &local_err);

        if (ret < 0) {

            goto fail;

        }

    } else if (!drv) {

        error_setg(errp, "Must specify either driver or file");

        ret = -EINVAL;

        goto fail;

    }

    /* Open the image */

    ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);

    if (ret < 0) {

        goto fail;

    }

    if (file && (bs->file != file)) {

        bdrv_unref(file);

        file = NULL;

    }

    /* If there is a backing file, use it */

    if ((flags & BDRV_O_NO_BACKING) == 0) {

        QDict *backing_options;

        qdict_extract_subqdict(options, &backing_options, "backing.");

        ret = bdrv_open_backing_file(bs, backing_options, &local_err);

        if (ret < 0) {

            goto close_and_fail;

        }

    }

    bdrv_refresh_filename(bs);

    /* For snapshot=on, create a temporary qcow2 overlay. bs points to the

     * temporary snapshot afterwards. */

    if (snapshot_flags) {

        ret = bdrv_append_temp_snapshot(bs, snapshot_flags, &local_err);

        if (local_err) {

            goto close_and_fail;

        }

    }

    /* Check if any unknown options were used */

    if (options && (qdict_size(options) != 0)) {

        const QDictEntry *entry = qdict_first(options);

        if (flags & BDRV_O_PROTOCOL) {

            error_setg(errp, "Block protocol '%s' doesn't support the option "

                       "'%s'", drv->format_name, entry->key);

        } else {

            error_setg(errp, "Block format '%s' used by device '%s' doesn't "

                       "support the option '%s'", drv->format_name,

                       bdrv_get_device_name(bs), entry->key);

        }

        ret = -EINVAL;

        goto close_and_fail;

    }

    if (!bdrv_key_required(bs)) {

        if (bs->blk) {

            blk_dev_change_media_cb(bs->blk, true);

        }

    } else if (!runstate_check(RUN_STATE_PRELAUNCH)

               && !runstate_check(RUN_STATE_INMIGRATE)

               && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */

        error_setg(errp,

                   "Guest must be stopped for opening of encrypted image");

        ret = -EBUSY;

        goto close_and_fail;

    }

    QDECREF(options);

    *pbs = bs;

    return 0;

fail:

    if (file != NULL) {

        bdrv_unref(file);

    }

    QDECREF(bs->options);

    QDECREF(options);

    bs->options = NULL;

    if (!*pbs) {

        /* If *pbs is NULL, a new BDS has been created in this function and

           needs to be freed now. Otherwise, it does not need to be closed,

           since it has not really been opened yet. */

        bdrv_unref(bs);

    }

    if (local_err) {

        error_propagate(errp, local_err);

    }

    return ret;

close_and_fail:

    /* See fail path, but now the BDS has to be always closed */

    if (*pbs) {

        bdrv_close(bs);

    } else {

        bdrv_unref(bs);

    }

    QDECREF(options);

    if (local_err) {

        error_propagate(errp, local_err);

    }

    return ret;

}


START_TEST(qdict_haskey_test)

{

    const char *key = "test";

    qdict_put(tests_dict, key, qint_from_int(0));

    fail_unless(qdict_haskey(tests_dict, key) == 1);

}


static void pc_dimm_check_memdev_is_busy(const Object *obj, const char *name,

                                      Object *val, Error **errp)

{

    Error *local_err = NULL;

    if (host_memory_backend_is_mapped(MEMORY_BACKEND(val))) {

        char *path = object_get_canonical_path_component(val);

        error_setg(&local_err, "can't use already busy memdev: %s", path);

        g_free(path);

    } else {

        qdev_prop_allow_set_link_before_realize(obj, name, val, &local_err);

    }

    error_propagate(errp, local_err);

}


void co_run_in_worker_bh(void *opaque)

{

    Coroutine *co = opaque;

    thread_pool_submit_aio(aio_get_thread_pool(qemu_get_aio_context()),

                           coroutine_enter_func, co, coroutine_enter_cb, co);

}


static int local_fstat(FsContext *ctx, int fd, struct stat *stbuf)

{

    return fstat(fd, stbuf);

}


static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,

                                     uint64_t sector, size_t size)

{

    uint64_t nb_sectors = size >> BDRV_SECTOR_BITS;

    uint64_t total_sectors;

    if (nb_sectors > INT_MAX) {

        return false;

    }

    if (sector & dev->sector_mask) {

        return false;

    }

    if (size % dev->conf.conf.logical_block_size) {

        return false;

    }

    blk_get_geometry(dev->blk, &total_sectors);

    if (sector > total_sectors || nb_sectors > total_sectors - sector) {

        return false;

    }

    return true;

}


static inline void RENAME(rgb16to15)(const uint8_t *src, uint8_t *dst, long src_size)

{

    register const uint8_t* s=src;

    register uint8_t* d=dst;

    register const uint8_t *end;

    const uint8_t *mm_end;

    end = s + src_size;

#if COMPILE_TEMPLATE_MMX

    __asm__ volatile(PREFETCH"    %0"::"m"(*s));

    __asm__ volatile("movq        %0, %%mm7"::"m"(mask15rg));

    __asm__ volatile("movq        %0, %%mm6"::"m"(mask15b));

    mm_end = end - 15;

    while (s<mm_end) {

        __asm__ volatile(

            PREFETCH"  32%1         \n\t"

            "movq        %1, %%mm0  \n\t"

            "movq       8%1, %%mm2  \n\t"

            "movq     %%mm0, %%mm1  \n\t"

            "movq     %%mm2, %%mm3  \n\t"

            "psrlq       $1, %%mm0  \n\t"

            "psrlq       $1, %%mm2  \n\t"

            "pand     %%mm7, %%mm0  \n\t"

            "pand     %%mm7, %%mm2  \n\t"

            "pand     %%mm6, %%mm1  \n\t"

            "pand     %%mm6, %%mm3  \n\t"

            "por      %%mm1, %%mm0  \n\t"

            "por      %%mm3, %%mm2  \n\t"

            MOVNTQ"   %%mm0,  %0    \n\t"

            MOVNTQ"   %%mm2, 8%0"

            :"=m"(*d)

            :"m"(*s)

        );

        d+=16;

        s+=16;

    }

    __asm__ volatile(SFENCE:::"memory");

    __asm__ volatile(EMMS:::"memory");

#endif

    mm_end = end - 3;

    while (s < mm_end) {

        register uint32_t x= *((const uint32_t*)s);

        *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F);

        s+=4;

        d+=4;

    }

    if (s < end) {

        register uint16_t x= *((const uint16_t*)s);

        *((uint16_t *)d) = ((x>>1)&0x7FE0) | (x&0x001F);

    }

}


static void do_interrupt64(CPUX86State *env, int intno, int is_int,

                           int error_code, target_ulong next_eip, int is_hw)

{

    SegmentCache *dt;

    target_ulong ptr;

    int type, dpl, selector, cpl, ist;

    int has_error_code, new_stack;

    uint32_t e1, e2, e3, ss;

    target_ulong old_eip, esp, offset;

    has_error_code = 0;

    if (!is_int && !is_hw) {

        has_error_code = exception_has_error_code(intno);

    }

    if (is_int) {

        old_eip = next_eip;

    } else {

        old_eip = env->eip;

    }

    dt = &env->idt;

    if (intno * 16 + 15 > dt->limit) {

        raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);

    }

    ptr = dt->base + intno * 16;

    e1 = cpu_ldl_kernel(env, ptr);

    e2 = cpu_ldl_kernel(env, ptr + 4);

    e3 = cpu_ldl_kernel(env, ptr + 8);

    /* check gate type */

    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;

    switch (type) {

    case 14: /* 386 interrupt gate */

    case 15: /* 386 trap gate */

        break;

    default:

        raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);

        break;

    }

    dpl = (e2 >> DESC_DPL_SHIFT) & 3;

    cpl = env->hflags & HF_CPL_MASK;

    /* check privilege if software int */

    if (is_int && dpl < cpl) {

        raise_exception_err(env, EXCP0D_GPF, intno * 16 + 2);

    }

    /* check valid bit */

    if (!(e2 & DESC_P_MASK)) {

        raise_exception_err(env, EXCP0B_NOSEG, intno * 16 + 2);

    }

    selector = e1 >> 16;

    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);

    ist = e2 & 7;

    if ((selector & 0xfffc) == 0) {

        raise_exception_err(env, EXCP0D_GPF, 0);

    }

    if (load_segment(env, &e1, &e2, selector) != 0) {

        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);

    }

    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) {

        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);

    }

    dpl = (e2 >> DESC_DPL_SHIFT) & 3;

    if (dpl > cpl) {

        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);

    }

    if (!(e2 & DESC_P_MASK)) {

        raise_exception_err(env, EXCP0B_NOSEG, selector & 0xfffc);

    }

    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK)) {

        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);

    }

    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {

        /* to inner privilege */

        if (ist != 0) {

            esp = get_rsp_from_tss(env, ist + 3);

        } else {

            esp = get_rsp_from_tss(env, dpl);

        }

        esp &= ~0xfLL; /* align stack */

        ss = 0;

        new_stack = 1;

    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {

        /* to same privilege */

        if (env->eflags & VM_MASK) {

            raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);

        }

        new_stack = 0;

        if (ist != 0) {

            esp = get_rsp_from_tss(env, ist + 3);

        } else {

            esp = env->regs[R_ESP];

        }

        esp &= ~0xfLL; /* align stack */

        dpl = cpl;

    } else {

        raise_exception_err(env, EXCP0D_GPF, selector & 0xfffc);

        new_stack = 0; /* avoid warning */

        esp = 0; /* avoid warning */

    }

    PUSHQ(esp, env->segs[R_SS].selector);

    PUSHQ(esp, env->regs[R_ESP]);

    PUSHQ(esp, cpu_compute_eflags(env));

    PUSHQ(esp, env->segs[R_CS].selector);

    PUSHQ(esp, old_eip);

    if (has_error_code) {

        PUSHQ(esp, error_code);

    }

    /* interrupt gate clear IF mask */

    if ((type & 1) == 0) {

        env->eflags &= ~IF_MASK;

    }

    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);

    if (new_stack) {

        ss = 0 | dpl;

        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);

    }

    env->regs[R_ESP] = esp;

    selector = (selector & ~3) | dpl;

    cpu_x86_load_seg_cache(env, R_CS, selector,

                   get_seg_base(e1, e2),

                   get_seg_limit(e1, e2),

                   e2);

    env->eip = offset;

}


static void sdhci_generic_reset(DeviceState *ds)

{

    SDHCIState *s = SDHCI(ds);

    SDHCI_GET_CLASS(s)->reset(s);

}


static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,

                                  int destidx, int element, TCGMemOp memop)

{

    int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);

    switch (memop) {

    case MO_8:

        tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);

        break;

    case MO_16:

        tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);

        break;

    case MO_32:

        tcg_gen_st_i32(tcg_src, cpu_env, vect_off);

        break;

    default:

        g_assert_not_reached();

    }

}


static void net_socket_cleanup(NetClientState *nc)

{

    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);

    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);

    close(s->fd);

}


void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)

{

    CharDriverState *chr;

    chr = qemu_chr_new("qtest", qtest_chrdev, NULL);

    if (chr == NULL) {

        error_setg(errp, "Failed to initialize device for qtest: \"%s\"",

                   qtest_chrdev);

        return;

    }

    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);

    qemu_chr_fe_set_echo(chr, true);

    inbuf = g_string_new("");

    if (qtest_log) {

        if (strcmp(qtest_log, "none") != 0) {

            qtest_log_fp = fopen(qtest_log, "w+");

        }

    } else {

        qtest_log_fp = stderr;

    }

    qtest_chr = chr;

}


static uint32_t taihu_cpld_readl (void *opaque, hwaddr addr)

{

    uint32_t ret;

    ret = taihu_cpld_readb(opaque, addr) << 24;

    ret |= taihu_cpld_readb(opaque, addr + 1) << 16;

    ret |= taihu_cpld_readb(opaque, addr + 2) << 8;

    ret |= taihu_cpld_readb(opaque, addr + 3);

    return ret;

}


static int htab_save_complete(QEMUFile *f, void *opaque)

{

    sPAPRMachineState *spapr = opaque;

    /* Iteration header */

    qemu_put_be32(f, 0);

    if (!spapr->htab) {

        int rc;

        assert(kvm_enabled());

        rc = spapr_check_htab_fd(spapr);

        if (rc < 0) {

            return rc;

        }

        rc = kvmppc_save_htab(f, spapr->htab_fd, MAX_KVM_BUF_SIZE, -1);

        if (rc < 0) {

            return rc;

        }

        close(spapr->htab_fd);

        spapr->htab_fd = -1;

    } else {

        htab_save_later_pass(f, spapr, -1);

    }

    /* End marker */

    qemu_put_be32(f, 0);

    qemu_put_be16(f, 0);

    qemu_put_be16(f, 0);

    return 0;

}


static uint32_t  ahci_port_read(AHCIState *s, int port, int offset)

{

    uint32_t val;

    AHCIPortRegs *pr;

    pr = &s->dev[port].port_regs;

    switch (offset) {

    case PORT_LST_ADDR:

        val = pr->lst_addr;

        break;

    case PORT_LST_ADDR_HI:

        val = pr->lst_addr_hi;

        break;

    case PORT_FIS_ADDR:

        val = pr->fis_addr;

        break;

    case PORT_FIS_ADDR_HI:

        val = pr->fis_addr_hi;

        break;

    case PORT_IRQ_STAT:

        val = pr->irq_stat;

        break;

    case PORT_IRQ_MASK:

        val = pr->irq_mask;

        break;

    case PORT_CMD:

        val = pr->cmd;

        break;

    case PORT_TFDATA:

        val = pr->tfdata;

        break;

    case PORT_SIG:

        val = pr->sig;

        break;

    case PORT_SCR_STAT:

        if (s->dev[port].port.ifs[0].bs) {

            val = SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP |

                  SATA_SCR_SSTATUS_SPD_GEN1 | SATA_SCR_SSTATUS_IPM_ACTIVE;

        } else {

            val = SATA_SCR_SSTATUS_DET_NODEV;

        }

        break;

    case PORT_SCR_CTL:

        val = pr->scr_ctl;

        break;

    case PORT_SCR_ERR:

        val = pr->scr_err;

        break;

    case PORT_SCR_ACT:

        pr->scr_act &= ~s->dev[port].finished;

        s->dev[port].finished = 0;

        val = pr->scr_act;

        break;

    case PORT_CMD_ISSUE:

        val = pr->cmd_issue;

        break;

    case PORT_RESERVED:

    default:

        val = 0;

    }

    DPRINTF(port, "offset: 0x%x val: 0x%x\n", offset, val);

    return val;

}


static void hscroll(AVCodecContext *avctx)

{

    AnsiContext *s = avctx->priv_data;

    int i;

    if (s->y < avctx->height - s->font_height) {

        s->y += s->font_height;

        return;

    }

    i = 0;

    for (; i < avctx->height - s->font_height; i++)

        memcpy(s->frame->data[0] + i * s->frame->linesize[0],

               s->frame->data[0] + (i + s->font_height) * s->frame->linesize[0],

               avctx->width);

    for (; i < avctx->height; i++)

        memset(s->frame->data[0] + i * s->frame->linesize[0],

            DEFAULT_BG_COLOR, avctx->width);

}


static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)

{

    QEMUFileBuffered *s = opaque;

    if (qemu_file_get_error(s->file)) {

        goto out;

    }

    if (new_rate > SIZE_MAX) {

        new_rate = SIZE_MAX;

    }

    s->xfer_limit = new_rate / 10;

out:

    return s->xfer_limit;

}


static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,

                            void *value, size_t size, int flags)

{

    char buffer[PATH_MAX];

    return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value,

            size, flags);

}


static int spapr_vio_check_reg(VIOsPAPRDevice *sdev, VIOsPAPRDeviceInfo *info)

{

    VIOsPAPRDevice *other_sdev;

    DeviceState *qdev;

    VIOsPAPRBus *sbus;

    sbus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus);

    /*

     * Check two device aren't given clashing addresses by the user (or some

     * other mechanism). We have to open code this because we have to check

     * for matches with devices other than us.

     */

    QTAILQ_FOREACH(qdev, &sbus->bus.children, sibling) {

        other_sdev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);

        if (other_sdev != sdev && other_sdev->reg == sdev->reg) {

            fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",

                    info->qdev.name, other_sdev->qdev.info->name, sdev->reg);

            return -EEXIST;

        }

    }

    return 0;

}


static int vaapi_encode_issue(AVCodecContext *avctx,

                              VAAPIEncodePicture *pic)

{

    VAAPIEncodeContext *ctx = avctx->priv_data;

    VAAPIEncodeSlice *slice;

    VAStatus vas;

    int err, i;

    char data[MAX_PARAM_BUFFER_SIZE];

    size_t bit_len;

    av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" "

           "as type %s.\n", pic->display_order, pic->encode_order,

           picture_type_name[pic->type]);

    if (pic->nb_refs == 0) {

        av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n");

    } else {

        av_log(avctx, AV_LOG_DEBUG, "Refers to:");

        for (i = 0; i < pic->nb_refs; i++) {

            av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,

                   pic->refs[i]->display_order, pic->refs[i]->encode_order);

        }

        av_log(avctx, AV_LOG_DEBUG, ".\n");

    }

    av_assert0(pic->input_available && !pic->encode_issued);

    for (i = 0; i < pic->nb_refs; i++) {

        av_assert0(pic->refs[i]);

        // If we are serialised then the references must have already

        // completed.  If not, they must have been issued but need not

        // have completed yet.

        if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING)

            av_assert0(pic->refs[i]->encode_complete);

        else

            av_assert0(pic->refs[i]->encode_issued);

    }

    av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface);

    pic->recon_image = av_frame_alloc();

    if (!pic->recon_image) {

        err = AVERROR(ENOMEM);

        goto fail;

    }

    err = av_hwframe_get_buffer(ctx->recon_frames_ref, pic->recon_image, 0);

    if (err < 0) {

        err = AVERROR(ENOMEM);

        goto fail;

    }

    pic->recon_surface = (VASurfaceID)(uintptr_t)pic->recon_image->data[3];

    av_log(avctx, AV_LOG_DEBUG, "Recon surface is %#x.\n", pic->recon_surface);

    pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool);

    if (!pic->output_buffer_ref) {

        err = AVERROR(ENOMEM);

        goto fail;

    }

    pic->output_buffer = (VABufferID)(uintptr_t)pic->output_buffer_ref->data;

    av_log(avctx, AV_LOG_DEBUG, "Output buffer is %#x.\n",

           pic->output_buffer);

    if (ctx->codec->picture_params_size > 0) {

        pic->codec_picture_params = av_malloc(ctx->codec->picture_params_size);

        if (!pic->codec_picture_params)

            goto fail;

        memcpy(pic->codec_picture_params, ctx->codec_picture_params,

               ctx->codec->picture_params_size);

    } else {

        av_assert0(!ctx->codec_picture_params);

    }

    pic->nb_param_buffers = 0;

    if (pic->encode_order == 0) {

        // Global parameter buffers are set on the first picture only.

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

            err = vaapi_encode_make_param_buffer(avctx, pic,

                                                 VAEncMiscParameterBufferType,

                                                 (char*)ctx->global_params[i],

                                                 ctx->global_params_size[i]);

            if (err < 0)

                goto fail;

        }

    }

    if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) {

        err = vaapi_encode_make_param_buffer(avctx, pic,

                                             VAEncSequenceParameterBufferType,

                                             ctx->codec_sequence_params,

                                             ctx->codec->sequence_params_size);

        if (err < 0)

            goto fail;

    }

    if (ctx->codec->init_picture_params) {

        err = ctx->codec->init_picture_params(avctx, pic);

        if (err < 0) {

            av_log(avctx, AV_LOG_ERROR, "Failed to initialise picture "

                   "parameters: %d.\n", err);

            goto fail;

        }

        err = vaapi_encode_make_param_buffer(avctx, pic,

                                             VAEncPictureParameterBufferType,

                                             pic->codec_picture_params,

                                             ctx->codec->picture_params_size);

        if (err < 0)

            goto fail;

    }

    if (pic->type == PICTURE_TYPE_IDR) {

        if (ctx->codec->write_sequence_header) {

            bit_len = 8 * sizeof(data);

            err = ctx->codec->write_sequence_header(avctx, data, &bit_len);

            if (err < 0) {

                av_log(avctx, AV_LOG_ERROR, "Failed to write per-sequence "

                       "header: %d.\n", err);

                goto fail;

            }

            err = vaapi_encode_make_packed_header(avctx, pic,

                                                  ctx->codec->sequence_header_type,

                                                  data, bit_len);

            if (err < 0)

                goto fail;

        }

    }

    if (ctx->codec->write_picture_header) {

        bit_len = 8 * sizeof(data);

        err = ctx->codec->write_picture_header(avctx, pic, data, &bit_len);

        if (err < 0) {

            av_log(avctx, AV_LOG_ERROR, "Failed to write per-picture "

                   "header: %d.\n", err);

            goto fail;

        }

        err = vaapi_encode_make_packed_header(avctx, pic,

                                              ctx->codec->picture_header_type,

                                              data, bit_len);

        if (err < 0)

            goto fail;

    }

    if (ctx->codec->write_extra_buffer) {

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

            size_t len = sizeof(data);

            int type;

            err = ctx->codec->write_extra_buffer(avctx, pic, i, &type,

                                                 data, &len);

            if (err == AVERROR_EOF)

                break;

            if (err < 0) {

                av_log(avctx, AV_LOG_ERROR, "Failed to write extra "

                       "buffer %d: %d.\n", i, err);

                goto fail;

            }

            err = vaapi_encode_make_param_buffer(avctx, pic, type,

                                                 data, len);

            if (err < 0)

                goto fail;

        }

    }

    if (ctx->codec->write_extra_header) {

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

            int type;

            bit_len = 8 * sizeof(data);

            err = ctx->codec->write_extra_header(avctx, pic, i, &type,

                                                 data, &bit_len);

            if (err == AVERROR_EOF)

                break;

            if (err < 0) {

                av_log(avctx, AV_LOG_ERROR, "Failed to write extra "

                       "header %d: %d.\n", i, err);

                goto fail;

            }

            err = vaapi_encode_make_packed_header(avctx, pic, type,

                                                  data, bit_len);

            if (err < 0)

                goto fail;

        }

    }

    av_assert0(pic->nb_slices <= MAX_PICTURE_SLICES);

    for (i = 0; i < pic->nb_slices; i++) {

        slice = av_mallocz(sizeof(*slice));

        if (!slice) {

            err = AVERROR(ENOMEM);

            goto fail;

        }

        pic->slices[i] = slice;

        if (ctx->codec->slice_params_size > 0) {

            slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size);

            if (!slice->codec_slice_params) {

                err = AVERROR(ENOMEM);

                goto fail;

            }

        }

        if (ctx->codec->init_slice_params) {

            err = ctx->codec->init_slice_params(avctx, pic, slice);

            if (err < 0) {

                av_log(avctx, AV_LOG_ERROR, "Failed to initalise slice "

                       "parameters: %d.\n", err);

                goto fail;

            }

        }

        if (ctx->codec->write_slice_header) {

            bit_len = 8 * sizeof(data);

            err = ctx->codec->write_slice_header(avctx, pic, slice,

                                                 data, &bit_len);

            if (err < 0) {

                av_log(avctx, AV_LOG_ERROR, "Failed to write per-slice "

                       "header: %d.\n", err);

                goto fail;

            }

            err = vaapi_encode_make_packed_header(avctx, pic,

                                                  ctx->codec->slice_header_type,

                                                  data, bit_len);

            if (err < 0)

                goto fail;

        }

        if (ctx->codec->init_slice_params) {

            err = vaapi_encode_make_param_buffer(avctx, pic,

                                                 VAEncSliceParameterBufferType,

                                                 slice->codec_slice_params,

                                                 ctx->codec->slice_params_size);

            if (err < 0)

                goto fail;

        }

    }

    vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,

                         pic->input_surface);

    if (vas != VA_STATUS_SUCCESS) {

        av_log(avctx, AV_LOG_ERROR, "Failed to begin picture encode issue: "

               "%d (%s).\n", vas, vaErrorStr(vas));

        err = AVERROR(EIO);

        goto fail_with_picture;

    }

    vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,

                          pic->param_buffers, pic->nb_param_buffers);

    if (vas != VA_STATUS_SUCCESS) {

        av_log(avctx, AV_LOG_ERROR, "Failed to upload encode parameters: "

               "%d (%s).\n", vas, vaErrorStr(vas));

        err = AVERROR(EIO);

        goto fail_with_picture;

    }

    vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);

    if (vas != VA_STATUS_SUCCESS) {

        av_log(avctx, AV_LOG_ERROR, "Failed to end picture encode issue: "

               "%d (%s).\n", vas, vaErrorStr(vas));

        err = AVERROR(EIO);

        // vaRenderPicture() has been called here, so we should not destroy

        // the parameter buffers unless separate destruction is required.

        if (ctx->hwctx->driver_quirks &

            AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS)

            goto fail;

        else

            goto fail_at_end;

    }

    if (ctx->hwctx->driver_quirks &

        AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) {

        for (i = 0; i < pic->nb_param_buffers; i++) {

            vas = vaDestroyBuffer(ctx->hwctx->display,

                                  pic->param_buffers[i]);

            if (vas != VA_STATUS_SUCCESS) {

                av_log(avctx, AV_LOG_ERROR, "Failed to destroy "

                       "param buffer %#x: %d (%s).\n",

                       pic->param_buffers[i], vas, vaErrorStr(vas));

                // And ignore.

            }

        }

    }

    pic->encode_issued = 1;

    if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING)

        return vaapi_encode_wait(avctx, pic);

    else

        return 0;

fail_with_picture:

    vaEndPicture(ctx->hwctx->display, ctx->va_context);

fail:

    for(i = 0; i < pic->nb_param_buffers; i++)

        vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]);

fail_at_end:

    av_freep(&pic->codec_picture_params);

    av_frame_free(&pic->recon_image);

    return err;

}


static void avc_luma_hv_qrt_8w_msa(const uint8_t *src_x, const uint8_t *src_y,

                                   int32_t src_stride, uint8_t *dst,

                                   int32_t dst_stride, int32_t height)

{

    uint32_t loop_cnt;

    v16i8 src_hz0, src_hz1, src_hz2, src_hz3;

    v16i8 src_vt0, src_vt1, src_vt2, src_vt3, src_vt4;

    v16i8 src_vt5, src_vt6, src_vt7, src_vt8;

    v16i8 mask0, mask1, mask2;

    v8i16 hz_out0, hz_out1, hz_out2, hz_out3;

    v8i16 vert_out0, vert_out1, vert_out2, vert_out3;

    v8i16 out0, out1, out2, out3;

    v16u8 tmp0, tmp1;

    LD_SB3(&luma_mask_arr[0], 16, mask0, mask1, mask2);

    LD_SB5(src_y, src_stride, src_vt0, src_vt1, src_vt2, src_vt3, src_vt4);

    src_y += (5 * src_stride);

    src_vt0 = (v16i8) __msa_insve_d((v2i64) src_vt0, 1, (v2i64) src_vt1);

    src_vt1 = (v16i8) __msa_insve_d((v2i64) src_vt1, 1, (v2i64) src_vt2);

    src_vt2 = (v16i8) __msa_insve_d((v2i64) src_vt2, 1, (v2i64) src_vt3);

    src_vt3 = (v16i8) __msa_insve_d((v2i64) src_vt3, 1, (v2i64) src_vt4);

    XORI_B4_128_SB(src_vt0, src_vt1, src_vt2, src_vt3);

    for (loop_cnt = (height >> 2); loop_cnt--;) {

        LD_SB4(src_x, src_stride, src_hz0, src_hz1, src_hz2, src_hz3);

        XORI_B4_128_SB(src_hz0, src_hz1, src_hz2, src_hz3);

        src_x += (4 * src_stride);

        hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2);

        hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2);

        hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2);

        hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2);

        SRARI_H4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 5);

        SAT_SH4_SH(hz_out0, hz_out1, hz_out2, hz_out3, 7);

        LD_SB4(src_y, src_stride, src_vt5, src_vt6, src_vt7, src_vt8);

        src_y += (4 * src_stride);

        src_vt4 = (v16i8) __msa_insve_d((v2i64) src_vt4, 1, (v2i64) src_vt5);

        src_vt5 = (v16i8) __msa_insve_d((v2i64) src_vt5, 1, (v2i64) src_vt6);

        src_vt6 = (v16i8) __msa_insve_d((v2i64) src_vt6, 1, (v2i64) src_vt7);

        src_vt7 = (v16i8) __msa_insve_d((v2i64) src_vt7, 1, (v2i64) src_vt8);

        XORI_B4_128_SB(src_vt4, src_vt5, src_vt6, src_vt7);

        /* filter calc */

        AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src_vt0, src_vt1, src_vt2, src_vt3,

                                        src_vt4, src_vt5, vert_out0, vert_out1);

        AVC_CALC_DPADD_B_6PIX_2COEFF_SH(src_vt2, src_vt3, src_vt4, src_vt5,

                                        src_vt6, src_vt7, vert_out2, vert_out3);

        SRARI_H4_SH(vert_out0, vert_out1, vert_out2, vert_out3, 5);

        SAT_SH4_SH(vert_out0, vert_out1, vert_out2, vert_out3, 7);

        out0 = __msa_srari_h((hz_out0 + vert_out0), 1);

        out1 = __msa_srari_h((hz_out1 + vert_out1), 1);

        out2 = __msa_srari_h((hz_out2 + vert_out2), 1);

        out3 = __msa_srari_h((hz_out3 + vert_out3), 1);

        SAT_SH4_SH(out0, out1, out2, out3, 7);

        tmp0 = PCKEV_XORI128_UB(out0, out1);

        tmp1 = PCKEV_XORI128_UB(out2, out3);

        ST8x4_UB(tmp0, tmp1, dst, dst_stride);

        dst += (4 * dst_stride);

        src_vt3 = src_vt7;

        src_vt1 = src_vt5;

        src_vt5 = src_vt4;

        src_vt4 = src_vt8;

        src_vt2 = src_vt6;

        src_vt0 = src_vt5;

    }

}


static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *surface_format,

                                 unsigned guid_count, const GUID *guid_list, GUID *decoder_guid)

{

    FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);

    unsigned i, j;

    *decoder_guid = ff_GUID_NULL;

    for (i = 0; dxva_modes[i].guid; i++) {

        const dxva_mode *mode = &dxva_modes[i];

        int validate;

        if (mode->codec != avctx->codec_id)

            continue;

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

            if (IsEqualGUID(mode->guid, &guid_list[j]))

                break;

        }

        if (j == guid_count)

            continue;

#if CONFIG_D3D11VA

        if (sctx->pix_fmt == AV_PIX_FMT_D3D11)

            validate = d3d11va_validate_output(service, *mode->guid, surface_format);

#endif

#if CONFIG_DXVA2

        if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)

            validate = dxva2_validate_output(service, *mode->guid, surface_format);

#endif

        if (validate) {

            *decoder_guid = *mode->guid;

            break;

        }

    }

    if (IsEqualGUID(decoder_guid, &ff_GUID_NULL)) {

        av_log(avctx, AV_LOG_VERBOSE, "No decoder device for codec found\n");

        return AVERROR(EINVAL);

    }

    if (IsEqualGUID(decoder_guid, &ff_DXVADDI_Intel_ModeH264_E))

        sctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;

    return 0;

}


static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)

{

    MpegEncContext *s = &ctx->m;

    int width, height, vo_ver_id;

    /* vol header */

    skip_bits(gb, 1);                   /* random access */

    s->vo_type = get_bits(gb, 8);

    if (get_bits1(gb) != 0) {           /* is_ol_id */

        vo_ver_id = get_bits(gb, 4);    /* vo_ver_id */

        skip_bits(gb, 3);               /* vo_priority */

    } else {

        vo_ver_id = 1;

    }

    s->aspect_ratio_info = get_bits(gb, 4);

    if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) {

        s->avctx->sample_aspect_ratio.num = get_bits(gb, 8);  // par_width

        s->avctx->sample_aspect_ratio.den = get_bits(gb, 8);  // par_height

    } else {

        s->avctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info];

    }

    if ((ctx->vol_control_parameters = get_bits1(gb))) { /* vol control parameter */

        int chroma_format = get_bits(gb, 2);

        if (chroma_format != CHROMA_420)

            av_log(s->avctx, AV_LOG_ERROR, "illegal chroma format\n");

        s->low_delay = get_bits1(gb);

        if (get_bits1(gb)) {    /* vbv parameters */

            get_bits(gb, 15);   /* first_half_bitrate */

            skip_bits1(gb);     /* marker */

            get_bits(gb, 15);   /* latter_half_bitrate */

            skip_bits1(gb);     /* marker */

            get_bits(gb, 15);   /* first_half_vbv_buffer_size */

            skip_bits1(gb);     /* marker */

            get_bits(gb, 3);    /* latter_half_vbv_buffer_size */

            get_bits(gb, 11);   /* first_half_vbv_occupancy */

            skip_bits1(gb);     /* marker */

            get_bits(gb, 15);   /* latter_half_vbv_occupancy */

            skip_bits1(gb);     /* marker */

        }

    } else {

        /* is setting low delay flag only once the smartest thing to do?

         * low delay detection won't be overridden. */

        if (s->picture_number == 0)

            s->low_delay = 0;

    }

    ctx->shape = get_bits(gb, 2); /* vol shape */

    if (ctx->shape != RECT_SHAPE)

        av_log(s->avctx, AV_LOG_ERROR, "only rectangular vol supported\n");

    if (ctx->shape == GRAY_SHAPE && vo_ver_id != 1) {

        av_log(s->avctx, AV_LOG_ERROR, "Gray shape not supported\n");

        skip_bits(gb, 4);  /* video_object_layer_shape_extension */

    }

    check_marker(gb, "before time_increment_resolution");

    s->avctx->framerate.num = get_bits(gb, 16);

    if (!s->avctx->framerate.num) {

        av_log(s->avctx, AV_LOG_ERROR, "framerate==0\n");

        return AVERROR_INVALIDDATA;

    }

    ctx->time_increment_bits = av_log2(s->avctx->framerate.num - 1) + 1;

    if (ctx->time_increment_bits < 1)

        ctx->time_increment_bits = 1;

    check_marker(gb, "before fixed_vop_rate");

    if (get_bits1(gb) != 0)     /* fixed_vop_rate  */

        s->avctx->framerate.den = get_bits(gb, ctx->time_increment_bits);

    else

        s->avctx->framerate.den = 1;

    s->avctx->time_base = av_inv_q(av_mul_q(s->avctx->framerate, (AVRational){s->avctx->ticks_per_frame, 1}));

    ctx->t_frame = 0;

    if (ctx->shape != BIN_ONLY_SHAPE) {

        if (ctx->shape == RECT_SHAPE) {

            check_marker(gb, "before width");

            width = get_bits(gb, 13);

            check_marker(gb, "before height");

            height = get_bits(gb, 13);

            check_marker(gb, "after height");

            if (width && height &&  /* they should be non zero but who knows */

                !(s->width && s->codec_tag == AV_RL32("MP4S"))) {

                if (s->width && s->height &&

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

                    s->context_reinit = 1;

                s->width  = width;

                s->height = height;

            }

        }

        s->progressive_sequence  =

        s->progressive_frame     = get_bits1(gb) ^ 1;

        s->interlaced_dct        = 0;

        if (!get_bits1(gb) && (s->avctx->debug & FF_DEBUG_PICT_INFO))

            av_log(s->avctx, AV_LOG_INFO,           /* OBMC Disable */

                   "MPEG4 OBMC not supported (very likely buggy encoder)\n");

        if (vo_ver_id == 1)

            ctx->vol_sprite_usage = get_bits1(gb);    /* vol_sprite_usage */

        else

            ctx->vol_sprite_usage = get_bits(gb, 2);  /* vol_sprite_usage */

        if (ctx->vol_sprite_usage == STATIC_SPRITE)

            av_log(s->avctx, AV_LOG_ERROR, "Static Sprites not supported\n");

        if (ctx->vol_sprite_usage == STATIC_SPRITE ||

            ctx->vol_sprite_usage == GMC_SPRITE) {

            if (ctx->vol_sprite_usage == STATIC_SPRITE) {

                skip_bits(gb, 13); // sprite_width

                skip_bits1(gb); /* marker */

                skip_bits(gb, 13); // sprite_height

                skip_bits1(gb); /* marker */

                skip_bits(gb, 13); // sprite_left

                skip_bits1(gb); /* marker */

                skip_bits(gb, 13); // sprite_top

                skip_bits1(gb); /* marker */

            }

            ctx->num_sprite_warping_points = get_bits(gb, 6);

            if (ctx->num_sprite_warping_points > 3) {

                av_log(s->avctx, AV_LOG_ERROR,

                       "%d sprite_warping_points\n",

                       ctx->num_sprite_warping_points);

                ctx->num_sprite_warping_points = 0;

                return AVERROR_INVALIDDATA;

            }

            s->sprite_warping_accuracy  = get_bits(gb, 2);

            ctx->sprite_brightness_change = get_bits1(gb);

            if (ctx->vol_sprite_usage == STATIC_SPRITE)

                skip_bits1(gb); // low_latency_sprite

        }

        // FIXME sadct disable bit if verid!=1 && shape not rect

        if (get_bits1(gb) == 1) {                   /* not_8_bit */

            s->quant_precision = get_bits(gb, 4);   /* quant_precision */

            if (get_bits(gb, 4) != 8)               /* bits_per_pixel */

                av_log(s->avctx, AV_LOG_ERROR, "N-bit not supported\n");

            if (s->quant_precision != 5)

                av_log(s->avctx, AV_LOG_ERROR,

                       "quant precision %d\n", s->quant_precision);

            if (s->quant_precision<3 || s->quant_precision>9) {

                s->quant_precision = 5;

            }

        } else {

            s->quant_precision = 5;

        }

        // FIXME a bunch of grayscale shape things

        if ((s->mpeg_quant = get_bits1(gb))) { /* vol_quant_type */

            int i, v;

            /* load default matrixes */

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

                int j = s->idsp.idct_permutation[i];

                v = ff_mpeg4_default_intra_matrix[i];

                s->intra_matrix[j]        = v;

                s->chroma_intra_matrix[j] = v;

                v = ff_mpeg4_default_non_intra_matrix[i];

                s->inter_matrix[j]        = v;

                s->chroma_inter_matrix[j] = v;

            }

            /* load custom intra matrix */

            if (get_bits1(gb)) {

                int last = 0;

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

                    int j;

                    v = get_bits(gb, 8);

                    if (v == 0)

                        break;

                    last = v;

                    j = s->idsp.idct_permutation[ff_zigzag_direct[i]];

                    s->intra_matrix[j]        = last;

                    s->chroma_intra_matrix[j] = last;

                }

                /* replicate last value */

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

                    int j = s->idsp.idct_permutation[ff_zigzag_direct[i]];

                    s->intra_matrix[j]        = last;

                    s->chroma_intra_matrix[j] = last;

                }

            }

            /* load custom non intra matrix */

            if (get_bits1(gb)) {

                int last = 0;

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

                    int j;

                    v = get_bits(gb, 8);

                    if (v == 0)

                        break;

                    last = v;

                    j = s->idsp.idct_permutation[ff_zigzag_direct[i]];

                    s->inter_matrix[j]        = v;

                    s->chroma_inter_matrix[j] = v;

                }

                /* replicate last value */

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

                    int j = s->idsp.idct_permutation[ff_zigzag_direct[i]];

                    s->inter_matrix[j]        = last;

                    s->chroma_inter_matrix[j] = last;

                }

            }

            // FIXME a bunch of grayscale shape things

        }

        if (vo_ver_id != 1)

            s->quarter_sample = get_bits1(gb);

        else

            s->quarter_sample = 0;

        if (get_bits_left(gb) < 4) {

            av_log(s->avctx, AV_LOG_ERROR, "VOL Header truncated\n");

            return AVERROR_INVALIDDATA;

        }

        if (!get_bits1(gb)) {

            int pos               = get_bits_count(gb);

            int estimation_method = get_bits(gb, 2);

            if (estimation_method < 2) {

                if (!get_bits1(gb)) {

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* opaque */

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* transparent */

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* intra_cae */

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* inter_cae */

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* no_update */

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* upampling */

                }

                if (!get_bits1(gb)) {

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* intra_blocks */

                    ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* inter_blocks */

                    ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* inter4v_blocks */

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* not coded blocks */

                }

                if (!check_marker(gb, "in complexity estimation part 1")) {

                    skip_bits_long(gb, pos - get_bits_count(gb));

                    goto no_cplx_est;

                }

                if (!get_bits1(gb)) {

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* dct_coeffs */

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* dct_lines */

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* vlc_syms */

                    ctx->cplx_estimation_trash_i += 4 * get_bits1(gb);  /* vlc_bits */

                }

                if (!get_bits1(gb)) {

                    ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* apm */

                    ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* npm */

                    ctx->cplx_estimation_trash_b += 8 * get_bits1(gb);  /* interpolate_mc_q */

                    ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* forwback_mc_q */

                    ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* halfpel2 */

                    ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* halfpel4 */

                }

                if (!check_marker(gb, "in complexity estimation part 2")) {

                    skip_bits_long(gb, pos - get_bits_count(gb));

                    goto no_cplx_est;

                }

                if (estimation_method == 1) {

                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* sadct */

                    ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* qpel */

                }

            } else

                av_log(s->avctx, AV_LOG_ERROR,

                       "Invalid Complexity estimation method %d\n",

                       estimation_method);

        } else {

no_cplx_est:

            ctx->cplx_estimation_trash_i =

            ctx->cplx_estimation_trash_p =

            ctx->cplx_estimation_trash_b = 0;

        }

        ctx->resync_marker = !get_bits1(gb); /* resync_marker_disabled */

        s->data_partitioning = get_bits1(gb);

        if (s->data_partitioning)

            ctx->rvlc = get_bits1(gb);

        if (vo_ver_id != 1) {

            ctx->new_pred = get_bits1(gb);

            if (ctx->new_pred) {

                av_log(s->avctx, AV_LOG_ERROR, "new pred not supported\n");

                skip_bits(gb, 2); /* requested upstream message type */

                skip_bits1(gb);   /* newpred segment type */

            }

            if (get_bits1(gb)) // reduced_res_vop

                av_log(s->avctx, AV_LOG_ERROR,

                       "reduced resolution VOP not supported\n");

        } else {

            ctx->new_pred = 0;

        }

        ctx->scalability = get_bits1(gb);

        if (ctx->scalability) {

            GetBitContext bak = *gb;

            int h_sampling_factor_n;

            int h_sampling_factor_m;

            int v_sampling_factor_n;

            int v_sampling_factor_m;

            skip_bits1(gb);    // hierarchy_type

            skip_bits(gb, 4);  /* ref_layer_id */

            skip_bits1(gb);    /* ref_layer_sampling_dir */

            h_sampling_factor_n = get_bits(gb, 5);

            h_sampling_factor_m = get_bits(gb, 5);

            v_sampling_factor_n = get_bits(gb, 5);

            v_sampling_factor_m = get_bits(gb, 5);

            ctx->enhancement_type = get_bits1(gb);

            if (h_sampling_factor_n == 0 || h_sampling_factor_m == 0 ||

                v_sampling_factor_n == 0 || v_sampling_factor_m == 0) {

                /* illegal scalability header (VERY broken encoder),

                 * trying to workaround */

                ctx->scalability = 0;

                *gb            = bak;

            } else

                av_log(s->avctx, AV_LOG_ERROR, "scalability not supported\n");

            // bin shape stuff FIXME

        }

    }

    if (s->avctx->debug&FF_DEBUG_PICT_INFO) {

        av_log(s->avctx, AV_LOG_DEBUG, "tb %d/%d, tincrbits:%d, qp_prec:%d, ps:%d,  %s%s%s%s\n",

               s->avctx->framerate.den, s->avctx->framerate.num,

               ctx->time_increment_bits,

               s->quant_precision,

               s->progressive_sequence,

               ctx->scalability ? "scalability " :"" , s->quarter_sample ? "qpel " : "",

               s->data_partitioning ? "partition " : "", ctx->rvlc ? "rvlc " : ""

        );

    }

    return 0;

}


static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)

{

    struct video_data *s = ctx->priv_data;

    struct v4l2_buffer buf = {

        .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,

        .memory = V4L2_MEMORY_MMAP

    };

    struct pollfd p = { .fd = s->fd, .events = POLLIN };

    int res;

    res = poll(&p, 1, s->timeout);

    if (res < 0)

        return AVERROR(errno);

    if (!(p.revents & (POLLIN | POLLERR | POLLHUP)))

        return AVERROR(EAGAIN);

    /* FIXME: Some special treatment might be needed in case of loss of signal... */

    while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));

    if (res < 0) {

        if (errno == EAGAIN) {

            pkt->size = 0;

            return AVERROR(EAGAIN);

        }

        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n",

               strerror(errno));

        return AVERROR(errno);

    }

    if (buf.index >= s->buffers) {

        av_log(ctx, AV_LOG_ERROR, "Invalid buffer index received.\n");

        return AVERROR(EINVAL);

    }

    avpriv_atomic_int_add_and_fetch(&s->buffers_queued, -1);

    // always keep at least one buffer queued

    av_assert0(avpriv_atomic_int_get(&s->buffers_queued) >= 1);

    if (s->frame_size > 0 && buf.bytesused != s->frame_size) {

        av_log(ctx, AV_LOG_ERROR,

               "The v4l2 frame is %d bytes, but %d bytes are expected\n",

               buf.bytesused, s->frame_size);

        return AVERROR_INVALIDDATA;

    }

    /* Image is at s->buff_start[buf.index] */

    if (avpriv_atomic_int_get(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) {

        /* when we start getting low on queued buffers, fall back on copying data */

        res = av_new_packet(pkt, buf.bytesused);

        if (res < 0) {

            av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");

            return res;

        }

        memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused);

        res = ioctl(s->fd, VIDIOC_QBUF, &buf);

        if (res < 0) {

            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");

            av_free_packet(pkt);

            return AVERROR(errno);

        }

        avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);

    } else {

        struct buff_data *buf_descriptor;

        pkt->data     = s->buf_start[buf.index];

        pkt->size     = buf.bytesused;

#if FF_API_DESTRUCT_PACKET

FF_DISABLE_DEPRECATION_WARNINGS

        pkt->destruct = dummy_release_buffer;

FF_ENABLE_DEPRECATION_WARNINGS

#endif

        buf_descriptor = av_malloc(sizeof(struct buff_data));

        if (buf_descriptor == NULL) {

            /* Something went wrong... Since av_malloc() failed, we cannot even

             * allocate a buffer for memcpying into it

             */

            av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");

            res = ioctl(s->fd, VIDIOC_QBUF, &buf);

            return AVERROR(ENOMEM);

        }

        buf_descriptor->fd    = s->fd;

        buf_descriptor->index = buf.index;

        buf_descriptor->s     = s;

        pkt->buf = av_buffer_create(pkt->data, pkt->size, mmap_release_buffer,

                                    buf_descriptor, 0);

        if (!pkt->buf) {

            av_freep(&buf_descriptor);

            return AVERROR(ENOMEM);

        }

    }

    pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;

    return s->buf_len[buf.index];

}


void cpu_ppc_set_papr(PowerPCCPU *cpu)

{

    CPUPPCState *env = &cpu->env;

    /* PAPR always has exception vectors in RAM not ROM. To ensure this,

     * MSR[IP] should never be set.

     *

     * We also disallow setting of MSR_HV

     */

    env->msr_mask &= ~((1ull << MSR_EP) | MSR_HVB);

    /* Set a full AMOR so guest can use the AMR as it sees fit */

    env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull;

    /* Tell KVM that we're in PAPR mode */

    if (kvm_enabled()) {

        kvmppc_set_papr(cpu);

    }

}


static int aac_encode_frame(AVCodecContext *avctx,

                            uint8_t *frame, int buf_size, void *data)

{

    AACEncContext *s = avctx->priv_data;

    int16_t *samples = s->samples, *samples2, *la;

    ChannelElement *cpe;

    int i, j, chans, tag, start_ch;

    const uint8_t *chan_map = aac_chan_configs[avctx->channels-1];

    int chan_el_counter[4];

    FFPsyWindowInfo windows[avctx->channels];

    if (s->last_frame)

        return 0;

    if (data) {

        if (!s->psypp) {

            memcpy(s->samples + 1024 * avctx->channels, data,

                   1024 * avctx->channels * sizeof(s->samples[0]));

        } else {

            start_ch = 0;

            samples2 = s->samples + 1024 * avctx->channels;

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

                tag = chan_map[i+1];

                chans = tag == TYPE_CPE ? 2 : 1;

                ff_psy_preprocess(s->psypp, (uint16_t*)data + start_ch,

                                  samples2 + start_ch, start_ch, chans);

                start_ch += chans;

            }

        }

    }

    if (!avctx->frame_number) {

        memcpy(s->samples, s->samples + 1024 * avctx->channels,

               1024 * avctx->channels * sizeof(s->samples[0]));

        return 0;

    }

    start_ch = 0;

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

        FFPsyWindowInfo* wi = windows + start_ch;

        tag      = chan_map[i+1];

        chans    = tag == TYPE_CPE ? 2 : 1;

        cpe      = &s->cpe[i];

        samples2 = samples + start_ch;

        la       = samples2 + 1024 * avctx->channels + start_ch;

        if (!data)

            la = NULL;

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

            IndividualChannelStream *ics = &cpe->ch[j].ics;

            int k;

            wi[j] = ff_psy_suggest_window(&s->psy, samples2, la, start_ch + j, ics->window_sequence[0]);

            ics->window_sequence[1] = ics->window_sequence[0];

            ics->window_sequence[0] = wi[j].window_type[0];

            ics->use_kb_window[1]   = ics->use_kb_window[0];

            ics->use_kb_window[0]   = wi[j].window_shape;

            ics->num_windows        = wi[j].num_windows;

            ics->swb_sizes          = s->psy.bands    [ics->num_windows == 8];

            ics->num_swb            = s->psy.num_bands[ics->num_windows == 8];

            for (k = 0; k < ics->num_windows; k++)

                ics->group_len[k] = wi[j].grouping[k];

            s->cur_channel = start_ch + j;

            apply_window_and_mdct(avctx, s, &cpe->ch[j], samples2, j);

        }

        start_ch += chans;

    }

    init_put_bits(&s->pb, frame, buf_size*8);

    if ((avctx->frame_number & 0xFF)==1 && !(avctx->flags & CODEC_FLAG_BITEXACT))

        put_bitstream_info(avctx, s, LIBAVCODEC_IDENT);

    start_ch = 0;

    memset(chan_el_counter, 0, sizeof(chan_el_counter));

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

        FFPsyWindowInfo* wi = windows + start_ch;

        tag      = chan_map[i+1];

        chans    = tag == TYPE_CPE ? 2 : 1;

        cpe      = &s->cpe[i];

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

            s->coder->search_for_quantizers(avctx, s, &cpe->ch[j], s->lambda);

        }

        cpe->common_window = 0;

        if (chans > 1

            && wi[0].window_type[0] == wi[1].window_type[0]

            && wi[0].window_shape   == wi[1].window_shape) {

            cpe->common_window = 1;

            for (j = 0; j < wi[0].num_windows; j++) {

                if (wi[0].grouping[j] != wi[1].grouping[j]) {

                    cpe->common_window = 0;

                    break;

                }

            }

        }

        if (cpe->common_window && s->coder->search_for_ms)

            s->coder->search_for_ms(s, cpe, s->lambda);

        adjust_frame_information(s, cpe, chans);

        put_bits(&s->pb, 3, tag);

        put_bits(&s->pb, 4, chan_el_counter[tag]++);

        if (chans == 2) {

            put_bits(&s->pb, 1, cpe->common_window);

            if (cpe->common_window) {

                put_ics_info(s, &cpe->ch[0].ics);

                encode_ms_info(&s->pb, cpe);

            }

        }

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

            s->cur_channel = start_ch + j;

            ff_psy_set_band_info(&s->psy, s->cur_channel, cpe->ch[j].coeffs, &wi[j]);

            encode_individual_channel(avctx, s, &cpe->ch[j], cpe->common_window);

        }

        start_ch += chans;

    }

    put_bits(&s->pb, 3, TYPE_END);

    flush_put_bits(&s->pb);

    avctx->frame_bits = put_bits_count(&s->pb);

    // rate control stuff

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

        float ratio = avctx->bit_rate * 1024.0f / avctx->sample_rate / avctx->frame_bits;

        s->lambda *= ratio;

        s->lambda = fminf(s->lambda, 65536.f);

    }

    if (avctx->frame_bits > 6144*avctx->channels)

        av_log(avctx, AV_LOG_ERROR, "input buffer violation %d > %d.\n",

               avctx->frame_bits, 6144*avctx->channels);

    if (!data)

        s->last_frame = 1;

    memcpy(s->samples, s->samples + 1024 * avctx->channels,

           1024 * avctx->channels * sizeof(s->samples[0]));

    return put_bits_count(&s->pb)>>3;

}


static int vc1_decode_intra_block(VC1Context *v, DCTELEM block[64], int n, int coded, int mquant, int codingset)

{

    GetBitContext *gb = &v->s.gb;

    MpegEncContext *s = &v->s;

    int dc_pred_dir = 0; /* Direction of the DC prediction used */

    int run_diff, i;

    int16_t *dc_val;

    int16_t *ac_val, *ac_val2;

    int dcdiff;

    int mb_pos = s->mb_x + s->mb_y * s->mb_stride;

    int a_avail, c_avail;

    /* XXX: Guard against dumb values of mquant */

    mquant = (mquant < 1) ? 0 : ( (mquant>31) ? 31 : mquant );

    /* Set DC scale - y and c use the same */

    s->y_dc_scale = s->y_dc_scale_table[mquant];

    s->c_dc_scale = s->c_dc_scale_table[mquant];

    /* check if prediction blocks A and C are available */

    a_avail = c_avail = 0;

    if((n == 2 || n == 3) || (s->mb_y && IS_INTRA(s->current_picture.mb_type[mb_pos - s->mb_stride])))

        a_avail = 1;

    if((n == 1 || n == 3) || (s->mb_x && IS_INTRA(s->current_picture.mb_type[mb_pos - 1])))

        c_avail = 1;

    /* Get DC differential */

    if (n < 4) {

        dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3);

    } else {

        dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3);

    }

    if (dcdiff < 0){

        av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n");

        return -1;

    }

    if (dcdiff)

    {

        if (dcdiff == 119 /* ESC index value */)

        {

            /* TODO: Optimize */

            if (mquant == 1) dcdiff = get_bits(gb, 10);

            else if (mquant == 2) dcdiff = get_bits(gb, 9);

            else dcdiff = get_bits(gb, 8);

        }

        else

        {

            if (mquant == 1)

                dcdiff = (dcdiff<<2) + get_bits(gb, 2) - 3;

            else if (mquant == 2)

                dcdiff = (dcdiff<<1) + get_bits(gb, 1) - 1;

        }

        if (get_bits(gb, 1))

            dcdiff = -dcdiff;

    }

    /* Prediction */

    dcdiff += vc1_pred_dc(&v->s, v->overlap, mquant, n, a_avail, c_avail, &dc_val, &dc_pred_dir);

    *dc_val = dcdiff;

    /* Store the quantized DC coeff, used for prediction */

    if (n < 4) {

        block[0] = dcdiff * s->y_dc_scale;

    } else {

        block[0] = dcdiff * s->c_dc_scale;

    }

    /* Skip ? */

    run_diff = 0;

    i = 0;

    if (!coded) {

        goto not_coded;

    }

    //AC Decoding

    i = 1;

    {

        int last = 0, skip, value;

        const int8_t *zz_table;

        int scale;

        int k;

        scale = mquant * 2 + v->halfpq;

        zz_table = vc1_simple_progressive_8x8_zz;

        ac_val = s->ac_val[0][0] + s->block_index[n] * 16;

        ac_val2 = ac_val;

        if(dc_pred_dir) //left

            ac_val -= 16;

        else //top

            ac_val -= 16 * s->block_wrap[n];

        while (!last) {

            vc1_decode_ac_coeff(v, &last, &skip, &value, codingset);

            i += skip;

            if(i > 63)

                break;

            block[zz_table[i++]] = value;

        }

        /* apply AC prediction if needed */

        if(s->ac_pred) {

            /* scale predictors if needed*/

            int mb_pos2, q1, q2;

            mb_pos2 = mb_pos - dc_pred_dir - (1 - dc_pred_dir) * s->mb_stride;

            q1 = s->current_picture.qscale_table[mb_pos];

            q2 = s->current_picture.qscale_table[mb_pos2];

            if(!c_avail) {

                memset(ac_val, 0, 8 * sizeof(ac_val[0]));

                dc_pred_dir = 0;

            }

            if(!a_avail) {

                memset(ac_val + 8, 0, 8 * sizeof(ac_val[0]));

                dc_pred_dir = 1;

            }

            if(!q1 && q1 && q2 && q1 != q2) {

                q1 = q1 * 2 - 1;

                q2 = q2 * 2 - 1;

                if(dc_pred_dir) { //left

                    for(k = 1; k < 8; k++)

                        block[k << 3] += (ac_val[k] * q2 * vc1_dqscale[q1 - 1] + 0x20000) >> 18;

                } else { //top

                    for(k = 1; k < 8; k++)

                        block[k] += (ac_val[k + 8] * q2 * vc1_dqscale[q1 - 1] + 0x20000) >> 18;

                }

            } else {

                if(dc_pred_dir) { //left

                    for(k = 1; k < 8; k++)

                        block[k << 3] += ac_val[k];

                } else { //top

                    for(k = 1; k < 8; k++)

                        block[k] += ac_val[k + 8];

                }

            }

        }

        /* save AC coeffs for further prediction */

        for(k = 1; k < 8; k++) {

            ac_val2[k] = block[k << 3];

            ac_val2[k + 8] = block[k];

        }

        /* scale AC coeffs */

        for(k = 1; k < 64; k++)

            if(block[k]) {

                block[k] *= scale;

                if(!v->pquantizer)

                    block[k] += (block[k] < 0) ? -mquant : mquant;

            }

        if(s->ac_pred) i = 63;

    }

not_coded:

    if(!coded) {

        int k, scale;

        ac_val = s->ac_val[0][0] + s->block_index[n] * 16;

        ac_val2 = ac_val;

        if(!c_avail) {

            memset(ac_val, 0, 8 * sizeof(ac_val[0]));

            dc_pred_dir = 0;

        }

        if(!a_avail) {

            memset(ac_val + 8, 0, 8 * sizeof(ac_val[0]));

            dc_pred_dir = 1;

        }

        scale = mquant * 2 + v->halfpq;

        memset(ac_val2, 0, 16 * 2);

        if(dc_pred_dir) {//left

            ac_val -= 16;

            if(s->ac_pred)

                memcpy(ac_val2, ac_val, 8 * 2);

        } else {//top

            ac_val -= 16 * s->block_wrap[n];

            if(s->ac_pred)

                memcpy(ac_val2 + 8, ac_val + 8, 8 * 2);

        }

        /* apply AC prediction if needed */

        if(s->ac_pred) {

            if(dc_pred_dir) { //left

                for(k = 1; k < 8; k++) {

                    block[k << 3] = ac_val[k] * scale;

                    if(!v->pquantizer)

                        block[k << 3] += (block[k << 3] < 0) ? -mquant : mquant;

                }

            } else { //top

                for(k = 1; k < 8; k++) {

                    block[k] = ac_val[k + 8] * scale;

                    if(!v->pquantizer)

                        block[k] += (block[k] < 0) ? -mquant : mquant;

                }

            }

            i = 63;

        }

    }

    s->block_last_index[n] = i;

    return 0;

}


static int vp3_decode_end(AVCodecContext *avctx)

{

    Vp3DecodeContext *s = avctx->priv_data;

    av_free(s->all_fragments);

    av_free(s->coded_fragment_list);

    av_free(s->superblock_fragments);

    av_free(s->superblock_macroblocks);

    av_free(s->macroblock_fragments);

    av_free(s->macroblock_coded);

    /* release all frames */

    avctx->release_buffer(avctx, &s->golden_frame);

    avctx->release_buffer(avctx, &s->last_frame);

    avctx->release_buffer(avctx, &s->current_frame);

    return 0;

}


static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)

{

    OpenPICState *opp = opaque;

    uint32_t retval;

    int idx;

    DPRINTF("%s: addr %08x\n", __func__, addr);

    retval = 0xFFFFFFFF;

    if (addr & 0xF) {

        return retval;

    }

    addr = addr & 0xFFF0;

    idx = addr >> 5;

    if (addr & 0x10) {

        /* EXDE / IFEDE / IEEDE */

        retval = read_IRQreg_ide(opp, idx);

    } else {

        /* EXVP / IFEVP / IEEVP */

        retval = read_IRQreg_ipvp(opp, idx);

    }

    DPRINTF("%s: => %08x\n", __func__, retval);

    return retval;

}


SchroFrame *ff_create_schro_frame(AVCodecContext *avccontext,

                                  SchroFrameFormat schro_frame_fmt)

{

    AVPicture *p_pic;

    SchroFrame *p_frame;

    int y_width, uv_width;

    int y_height, uv_height;

    int i;

    y_width   = avccontext->width;

    y_height  = avccontext->height;

    uv_width  = y_width  >> (SCHRO_FRAME_FORMAT_H_SHIFT(schro_frame_fmt));

    uv_height = y_height >> (SCHRO_FRAME_FORMAT_V_SHIFT(schro_frame_fmt));

    p_pic = av_mallocz(sizeof(AVPicture));

    avpicture_alloc(p_pic, avccontext->pix_fmt, y_width, y_height);

    p_frame         = schro_frame_new();

    p_frame->format = schro_frame_fmt;

    p_frame->width  = y_width;

    p_frame->height = y_height;

    schro_frame_set_free_callback(p_frame, free_schro_frame, (void *)p_pic);

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

        p_frame->components[i].width  = i ? uv_width : y_width;

        p_frame->components[i].stride = p_pic->linesize[i];

        p_frame->components[i].height = i ? uv_height : y_height;

        p_frame->components[i].length =

                 p_frame->components[i].stride * p_frame->components[i].height;

        p_frame->components[i].data   = p_pic->data[i];

        if (i) {

            p_frame->components[i].v_shift =

                SCHRO_FRAME_FORMAT_V_SHIFT(p_frame->format);

            p_frame->components[i].h_shift =

                SCHRO_FRAME_FORMAT_H_SHIFT(p_frame->format);

        }

    }

    return p_frame;

}


static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags)

{

    FFMContext *ffm = s->priv_data;

    int64_t pos_min, pos_max, pos;

    int64_t pts_min, pts_max, pts;

    double pos1;

    av_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0);

    /* find the position using linear interpolation (better than

       dichotomy in typical cases) */

    if (ffm->write_index && ffm->write_index < ffm->file_size) {

        if (get_dts(s, FFM_PACKET_SIZE) < wanted_pts) {

            pos_min = FFM_PACKET_SIZE;

            pos_max = ffm->write_index - FFM_PACKET_SIZE;

        } else {

            pos_min = ffm->write_index;

            pos_max = ffm->file_size - FFM_PACKET_SIZE;

        }

    } else {

        pos_min = FFM_PACKET_SIZE;

        pos_max = ffm->file_size - FFM_PACKET_SIZE;

    }

    while (pos_min <= pos_max) {

        pts_min = get_dts(s, pos_min);

        pts_max = get_dts(s, pos_max);

        if (pts_min > wanted_pts || pts_max <= wanted_pts) {

            pos = pts_min > wanted_pts ? pos_min : pos_max;

            goto found;

        }

        /* linear interpolation */

        pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /

            (double)(pts_max - pts_min);

        pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;

        if (pos <= pos_min)

            pos = pos_min;

        else if (pos >= pos_max)

            pos = pos_max;

        pts = get_dts(s, pos);

        /* check if we are lucky */

        if (pts == wanted_pts) {

            goto found;

        } else if (pts > wanted_pts) {

            pos_max = pos - FFM_PACKET_SIZE;

        } else {

            pos_min = pos + FFM_PACKET_SIZE;

        }

    }

    pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;

 found:

    if (ffm_seek1(s, pos) < 0)

        return -1;

    /* reset read state */

    ffm->read_state = READ_HEADER;

    ffm->packet_ptr = ffm->packet;

    ffm->packet_end = ffm->packet;

    ffm->first_packet = 1;

    return 0;

}


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

{

    MoxieCPU *cpu = MOXIE_CPU(dev);

    MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(dev);

    cpu_reset(CPU(cpu));

    mcc->parent_realize(dev, errp);

}


int ga_install_service(const char *path, const char *logfile)

{

    SC_HANDLE manager;

    SC_HANDLE service;

    TCHAR cmdline[MAX_PATH];

    if (GetModuleFileName(NULL, cmdline, MAX_PATH) == 0) {

        printf_win_error("No full path to service's executable");

        return EXIT_FAILURE;

    }

    _snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -d", cmdline);

    if (path) {

        _snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -p %s", cmdline, path);

    }

    if (logfile) {

        _snprintf(cmdline, MAX_PATH - strlen(cmdline), "%s -l %s -v",

            cmdline, logfile);

    }

    g_debug("service's cmdline: %s", cmdline);

    manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (manager == NULL) {

        printf_win_error("No handle to service control manager");

        return EXIT_FAILURE;

    }

    service = CreateService(manager, QGA_SERVICE_NAME, QGA_SERVICE_DISPLAY_NAME,

        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,

        SERVICE_ERROR_NORMAL, cmdline, NULL, NULL, NULL, NULL, NULL);

    if (service) {

        SERVICE_DESCRIPTION desc = { (char *)QGA_SERVICE_DESCRIPTION };

        ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &desc);

        printf("Service was installed successfully.\n");

    } else {

        printf_win_error("Failed to install service");

    }

    CloseServiceHandle(service);

    CloseServiceHandle(manager);

    return (service == NULL);

}