static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,

                                       Error **errp)

{

    Error *local_err = NULL;

    BlockMeasureInfo *info;

    uint64_t required = 0; /* bytes that contribute to required size */

    uint64_t virtual_size; /* disk size as seen by guest */

    uint64_t refcount_bits;

    uint64_t l2_tables;

    size_t cluster_size;

    int version;

    char *optstr;

    PreallocMode prealloc;

    bool has_backing_file;

    /* Parse image creation options */

    cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);

    if (local_err) {

        goto err;

    }

    version = qcow2_opt_get_version_del(opts, &local_err);

    if (local_err) {

        goto err;

    }

    refcount_bits = qcow2_opt_get_refcount_bits_del(opts, version, &local_err);

    if (local_err) {

        goto err;

    }

    optstr = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);

    prealloc = qapi_enum_parse(&PreallocMode_lookup, optstr,

                               PREALLOC_MODE_OFF, &local_err);

    g_free(optstr);

    if (local_err) {

        goto err;

    }

    optstr = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);

    has_backing_file = !!optstr;

    g_free(optstr);

    virtual_size = align_offset(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),

                                cluster_size);

    /* Check that virtual disk size is valid */

    l2_tables = DIV_ROUND_UP(virtual_size / cluster_size,

                             cluster_size / sizeof(uint64_t));

    if (l2_tables * sizeof(uint64_t) > QCOW_MAX_L1_SIZE) {

        error_setg(&local_err, "The image size is too large "

                               "(try using a larger cluster size)");

        goto err;

    }

    /* Account for input image */

    if (in_bs) {

        int64_t ssize = bdrv_getlength(in_bs);

        if (ssize < 0) {

            error_setg_errno(&local_err, -ssize,

                             "Unable to get image virtual_size");

            goto err;

        }

        virtual_size = align_offset(ssize, cluster_size);

        if (has_backing_file) {

            /* We don't how much of the backing chain is shared by the input

             * image and the new image file.  In the worst case the new image's

             * backing file has nothing in common with the input image.  Be

             * conservative and assume all clusters need to be written.

             */

            required = virtual_size;

        } else {

            int64_t offset;

            int pnum = 0;

            for (offset = 0; offset < ssize;

                 offset += pnum * BDRV_SECTOR_SIZE) {

                int nb_sectors = MIN(ssize - offset,

                                     BDRV_REQUEST_MAX_BYTES) / BDRV_SECTOR_SIZE;

                BlockDriverState *file;

                int64_t ret;

                ret = bdrv_get_block_status_above(in_bs, NULL,

                                                  offset >> BDRV_SECTOR_BITS,

                                                  nb_sectors,

                                                  &pnum, &file);

                if (ret < 0) {

                    error_setg_errno(&local_err, -ret,

                                     "Unable to get block status");

                    goto err;

                }

                if (ret & BDRV_BLOCK_ZERO) {

                    /* Skip zero regions (safe with no backing file) */

                } else if ((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) ==

                           (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) {

                    /* Extend pnum to end of cluster for next iteration */

                    pnum = (ROUND_UP(offset + pnum * BDRV_SECTOR_SIZE,

                                 cluster_size) - offset) >> BDRV_SECTOR_BITS;

                    /* Count clusters we've seen */

                    required += offset % cluster_size + pnum * BDRV_SECTOR_SIZE;

                }

            }

        }

    }

    /* Take into account preallocation.  Nothing special is needed for

     * PREALLOC_MODE_METADATA since metadata is always counted.

     */

    if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) {

        required = virtual_size;

    }

    info = g_new(BlockMeasureInfo, 1);

    info->fully_allocated =

        qcow2_calc_prealloc_size(virtual_size, cluster_size,

                                 ctz32(refcount_bits));

    /* Remove data clusters that are not required.  This overestimates the

     * required size because metadata needed for the fully allocated file is

     * still counted.

     */

    info->required = info->fully_allocated - virtual_size + required;

    return info;

err:

    error_propagate(errp, local_err);

    return NULL;

}


static void raw_aio_cancel(BlockDriverAIOCB *blockacb)

{

    int ret;

    RawAIOCB *acb = (RawAIOCB *)blockacb;

    RawAIOCB **pacb;

    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);

    if (ret == AIO_NOTCANCELED) {

        /* fail safe: if the aio could not be canceled, we wait for

           it */

        while (aio_error(&acb->aiocb) == EINPROGRESS);

    }

    /* remove the callback from the queue */

    pacb = &posix_aio_state->first_aio;

    for(;;) {

        if (*pacb == NULL) {

            break;

        } else if (*pacb == acb) {

            *pacb = acb->next;

            raw_fd_pool_put(acb);

            qemu_aio_release(acb);

            break;

        }

        pacb = &acb->next;

    }

}


void check_file_fixed_eof_mmaps(void)

{

	char *addr;

	char *cp;

	unsigned int *p1;

	uintptr_t p;

	int i;

	/* Find a suitable address to start with.  */

	addr = mmap(NULL, pagesize * 44, PROT_READ,

		    MAP_PRIVATE | MAP_ANONYMOUS,

		    -1, 0);

	fprintf (stderr, "%s addr=%p", __func__, (void *)addr);

	fail_unless (addr != MAP_FAILED);

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

	{

		/* Create submaps within our unfixed map.  */

		p1 = mmap(addr, pagesize, PROT_READ,

			  MAP_PRIVATE | MAP_FIXED,

			  test_fd,

			  (test_fsize - sizeof *p1) & ~pagemask);

		fail_unless (p1 != MAP_FAILED);

		/* Make sure we get pages aligned with the pagesize. The

		   target expects this.  */

		p = (uintptr_t) p1;

		fail_unless ((p & pagemask) == 0);

		/* Verify that the file maps was made correctly.  */

		fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]

			     == ((test_fsize - sizeof *p1) / sizeof *p1));

		/* Verify that the end of page is accessable and zeroed.  */

		cp = (void *)p1;

		fail_unless (cp[pagesize - 4] == 0);

		munmap (p1, pagesize);

		addr += pagesize;

	}

	fprintf (stderr, " passed\n");

}


static void nbd_attach_aio_context(BlockDriverState *bs,

                                   AioContext *new_context)

{

    BDRVNBDState *s = bs->opaque;

    nbd_client_session_attach_aio_context(&s->client, new_context);

}


void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)

{

    BMDMAState *bm = opaque;

#ifdef DEBUG_IDE

    printf("%s: 0x%08x\n", __func__, val);

#endif

    /* Ignore writes to SSBM if it keeps the old value */

    if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {

        if (!(val & BM_CMD_START)) {

            /*

             * We can't cancel Scatter Gather DMA in the middle of the

             * operation or a partial (not full) DMA transfer would reach

             * the storage so we wait for completion instead (we beahve

             * like if the DMA was completed by the time the guest trying

             * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not

             * set).

             *

             * In the future we'll be able to safely cancel the I/O if the

             * whole DMA operation will be submitted to disk with a single

             * aio operation with preadv/pwritev.

             */

            if (bm->bus->dma->aiocb) {

                qemu_aio_flush();

#ifdef DEBUG_IDE

                if (bm->bus->dma->aiocb)

                    printf("ide_dma_cancel: aiocb still pending\n");

                if (bm->status & BM_STATUS_DMAING)

                    printf("ide_dma_cancel: BM_STATUS_DMAING still pending\n");

#endif

            }

        } else {

            bm->cur_addr = bm->addr;

            if (!(bm->status & BM_STATUS_DMAING)) {

                bm->status |= BM_STATUS_DMAING;

                /* start dma transfer if possible */

                if (bm->dma_cb)

                    bm->dma_cb(bmdma_active_if(bm), 0);

            }

        }

    }

    bm->cmd = val & 0x09;

}


uint32_t qemu_devtree_get_phandle(void *fdt, const char *path)

{

    uint32_t r;

    r = fdt_get_phandle(fdt, findnode_nofail(fdt, path));

    if (r <= 0) {

        fprintf(stderr, "%s: Couldn't get phandle for %s: %s\n", __func__,

                path, fdt_strerror(r));

        exit(1);

    }

    return r;

}


static char *SocketAddress_to_str(const char *prefix, SocketAddressLegacy *addr,

                                  bool is_listen, bool is_telnet)

{

    switch (addr->type) {

    case SOCKET_ADDRESS_LEGACY_KIND_INET:

        return g_strdup_printf("%s%s:%s:%s%s", prefix,

                               is_telnet ? "telnet" : "tcp",

                               addr->u.inet.data->host,

                               addr->u.inet.data->port,

                               is_listen ? ",server" : "");

        break;

    case SOCKET_ADDRESS_LEGACY_KIND_UNIX:

        return g_strdup_printf("%sunix:%s%s", prefix,

                               addr->u.q_unix.data->path,

                               is_listen ? ",server" : "");

        break;

    case SOCKET_ADDRESS_LEGACY_KIND_FD:

        return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.data->str,

                               is_listen ? ",server" : "");

        break;

    case SOCKET_ADDRESS_LEGACY_KIND_VSOCK:

        return g_strdup_printf("%svsock:%s:%s", prefix,

                               addr->u.vsock.data->cid,

                               addr->u.vsock.data->port);

    default:

        abort();

    }

}


void handle_vm86_fault(CPUX86State *env)

{

    TaskState *ts = env->opaque;

    uint8_t *csp, *pc, *ssp;

    unsigned int ip, sp, newflags, newip, newcs, opcode, intno;

    int data32, pref_done;

    csp = (uint8_t *)(env->segs[R_CS] << 4);

    ip = env->eip & 0xffff;

    pc = csp + ip;

    ssp = (uint8_t *)(env->segs[R_SS] << 4);

    sp = env->regs[R_ESP] & 0xffff;

#if defined(DEBUG_VM86)

    fprintf(logfile, "VM86 exception %04x:%08x %02x %02x\n",

            env->segs[R_CS], env->eip, pc[0], pc[1]);

#endif

    data32 = 0;

    pref_done = 0;

    do {

        opcode = csp[ip];

        ADD16(ip, 1);

        switch (opcode) {

        case 0x66:      /* 32-bit data */     data32=1; break;

        case 0x67:      /* 32-bit address */  break;

        case 0x2e:      /* CS */              break;

        case 0x3e:      /* DS */              break;

        case 0x26:      /* ES */              break;

        case 0x36:      /* SS */              break;

        case 0x65:      /* GS */              break;

        case 0x64:      /* FS */              break;

        case 0xf2:      /* repnz */	      break;

        case 0xf3:      /* rep */             break;

        default: pref_done = 1;

        }

    } while (!pref_done);

    /* VM86 mode */

    switch(opcode) {

    case 0x9c: /* pushf */

        ADD16(env->eip, 2);

        if (data32) {

            vm_putl(ssp, sp - 4, get_vflags(env));

            ADD16(env->regs[R_ESP], -4);

        } else {

            vm_putw(ssp, sp - 2, get_vflags(env));

            ADD16(env->regs[R_ESP], -2);

        }

        env->eip = ip;

        VM86_FAULT_RETURN;

    case 0x9d: /* popf */

        if (data32) {

            newflags = vm_getl(ssp, sp);

            ADD16(env->regs[R_ESP], 4);

        } else {

            newflags = vm_getw(ssp, sp);

            ADD16(env->regs[R_ESP], 2);

        }

        env->eip = ip;

        CHECK_IF_IN_TRAP();

        if (data32) {

            if (set_vflags_long(newflags, env))

                return;

        } else {

            if (set_vflags_short(newflags, env))

                return;

        }

        VM86_FAULT_RETURN;

    case 0xcd: /* int */

        intno = csp[ip];

        ADD16(ip, 1);

        env->eip = ip;

        if (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) {

            if ( (ts->vm86plus.vm86plus.vm86dbg_intxxtab[intno >> 3] >>

                  (intno &7)) & 1) {

                return_to_32bit(env, TARGET_VM86_INTx + (intno << 8));

                return;

            }

        }

        do_int(env, intno);

        break;

    case 0xcf: /* iret */

        if (data32) {

            newip = vm_getl(ssp, sp) & 0xffff;

            newcs = vm_getl(ssp, sp + 4) & 0xffff;

            newflags = vm_getl(ssp, sp + 8);

            ADD16(env->regs[R_ESP], 12);

        } else {

            newip = vm_getw(ssp, sp);

            newcs = vm_getw(ssp, sp + 2);

            newflags = vm_getw(ssp, sp + 4);

            ADD16(env->regs[R_ESP], 6);

        }

        env->eip = newip;

        cpu_x86_load_seg(env, R_CS, newcs);

        CHECK_IF_IN_TRAP();

        if (data32) {

            if (set_vflags_long(newflags, env))

                return;

        } else {

            if (set_vflags_short(newflags, env))

                return;

        }

        VM86_FAULT_RETURN;

    case 0xfa: /* cli */

        env->eip = ip;

        clear_IF(env);

        VM86_FAULT_RETURN;

    case 0xfb: /* sti */

        env->eip = ip;

        if (set_IF(env))

            return;

        VM86_FAULT_RETURN;

    default:

        /* real VM86 GPF exception */

        return_to_32bit(env, TARGET_VM86_UNKNOWN);

        break;

    }

}


static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,

                                 uint32_t value, MemTxAttrs attrs)

{

    switch (offset) {

    case 0x00: /* Control */

        gic_set_cpu_control(s, cpu, value, attrs);

        break;

    case 0x04: /* Priority mask */

        s->priority_mask[cpu] = (value & 0xff);

        break;

    case 0x08: /* Binary Point */

        if (s->security_extn && !attrs.secure) {

            s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR);

        } else {

            s->bpr[cpu] = MAX(value & 0x7, GIC_MIN_BPR);

        }

        break;

    case 0x10: /* End Of Interrupt */

        gic_complete_irq(s, cpu, value & 0x3ff);

        return MEMTX_OK;

    case 0x1c: /* Aliased Binary Point */

        if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) {

            /* unimplemented, or NS access: RAZ/WI */

            return MEMTX_OK;

        } else {

            s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR);

        }

        break;

    case 0xd0: case 0xd4: case 0xd8: case 0xdc:

        qemu_log_mask(LOG_UNIMP, "Writing APR not implemented\n");

        break;

    default:

        qemu_log_mask(LOG_GUEST_ERROR,

                      "gic_cpu_write: Bad offset %x\n", (int)offset);

        return MEMTX_ERROR;

    }

    gic_update(s);

    return MEMTX_OK;

}


static int op_to_movi(int op)

{

    switch (op_bits(op)) {

    case 32:

        return INDEX_op_movi_i32;

#if TCG_TARGET_REG_BITS == 64

    case 64:

        return INDEX_op_movi_i64;

#endif

    default:

        fprintf(stderr, "op_to_movi: unexpected return value of "

                "function op_bits.\n");

        tcg_abort();

    }

}


static void dbdma_end(DBDMA_io *io)

{

    DBDMA_channel *ch = io->channel;

    dbdma_cmd *current = &ch->current;

    if (conditional_wait(ch))

        goto wait;

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

    current->res_count = cpu_to_le16(be32_to_cpu(io->len));

    dbdma_cmdptr_save(ch);

    if (io->is_last)

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

    conditional_interrupt(ch);

    conditional_branch(ch);

wait:

    ch->processing = 0;

    if ((ch->regs[DBDMA_STATUS] & cpu_to_be32(RUN)) &&

        (ch->regs[DBDMA_STATUS] & cpu_to_be32(ACTIVE)))

        channel_run(ch);

}


static void nfs_process_read(void *arg)

{

    NFSClient *client = arg;

    aio_context_acquire(client->aio_context);

    nfs_service(client->context, POLLIN);

    nfs_set_events(client);

    aio_context_release(client->aio_context);

}


int qemu_init_main_loop(void)

{

    int ret;

    qemu_init_sigbus();

    ret = qemu_signal_init();

    if (ret) {

        return ret;

    }

    /* Note eventfd must be drained before signalfd handlers run */

    ret = qemu_event_init();

    if (ret) {

        return ret;

    }

    qemu_cond_init(&qemu_cpu_cond);

    qemu_cond_init(&qemu_system_cond);

    qemu_cond_init(&qemu_pause_cond);

    qemu_cond_init(&qemu_work_cond);

    qemu_cond_init(&qemu_io_proceeded_cond);

    qemu_mutex_init(&qemu_global_mutex);

    qemu_mutex_lock(&qemu_global_mutex);

    qemu_thread_get_self(&io_thread);

    return 0;

}


static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)

{

    /* should be the case, see cirrus_bitblt_start */

    assert(s->cirrus_blt_width > 0);

    assert(s->cirrus_blt_height > 0);

    if (s->cirrus_blt_width > CIRRUS_BLTBUFSIZE) {

        return true;

    }

    if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,

                              s->cirrus_blt_dstaddr & s->cirrus_addr_mask)) {

        return true;

    }

    if (dst_only) {

        return false;

    }

    if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,

                              s->cirrus_blt_srcaddr & s->cirrus_addr_mask)) {

        return true;

    }

    return false;

}


static void virtio_pci_register_devices(void)

{

    type_register_static(&virtio_blk_info);

    type_register_static_alias(&virtio_blk_info, "virtio-blk");

    type_register_static(&virtio_net_info);

    type_register_static_alias(&virtio_net_info, "virtio-net");

    type_register_static(&virtio_serial_info);

    type_register_static_alias(&virtio_serial_info, "virtio-serial");

    type_register_static(&virtio_balloon_info);

    type_register_static_alias(&virtio_balloon_info, "virtio-balloon");

}


static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,

                                    uint64_t *data, unsigned size,

                                    MemTxAttrs attrs)

{

    NVICState *s = (NVICState *)opaque;

    uint32_t offset = addr;

    unsigned i, startvec, end;

    uint32_t val;

    if (attrs.user && !nvic_user_access_ok(s, addr)) {

        /* Generate BusFault for unprivileged accesses */

        return MEMTX_ERROR;

    }

    switch (offset) {

    /* reads of set and clear both return the status */

    case 0x100 ... 0x13f: /* NVIC Set enable */

        offset += 0x80;

        /* fall through */

    case 0x180 ... 0x1bf: /* NVIC Clear enable */

        val = 0;

        startvec = offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {

            if (s->vectors[startvec + i].enabled) {

                val |= (1 << i);

            }

        }

        break;

    case 0x200 ... 0x23f: /* NVIC Set pend */

        offset += 0x80;

        /* fall through */

    case 0x280 ... 0x2bf: /* NVIC Clear pend */

        val = 0;

        startvec = offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {

            if (s->vectors[startvec + i].pending) {

                val |= (1 << i);

            }

        }

        break;

    case 0x300 ... 0x33f: /* NVIC Active */

        val = 0;

        startvec = offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {

            if (s->vectors[startvec + i].active) {

                val |= (1 << i);

            }

        }

        break;

    case 0x400 ... 0x5ef: /* NVIC Priority */

        val = 0;

        startvec = offset - 0x400 + NVIC_FIRST_IRQ; /* vector # */

        for (i = 0; i < size && startvec + i < s->num_irq; i++) {

            val |= s->vectors[startvec + i].prio << (8 * i);

        }

        break;

    case 0xd18 ... 0xd23: /* System Handler Priority.  */

        val = 0;

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

            val |= s->vectors[(offset - 0xd14) + i].prio << (i * 8);

        }

        break;

    case 0xfe0 ... 0xfff: /* ID.  */

        if (offset & 3) {

            val = 0;

        } else {

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

        }

        break;

    default:

        if (size == 4) {

            val = nvic_readl(s, offset);

        } else {

            qemu_log_mask(LOG_GUEST_ERROR,

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

                          size, offset);

            val = 0;

        }

    }

    trace_nvic_sysreg_read(addr, val, size);

    *data = val;

    return MEMTX_OK;

}


coroutine_fn iscsi_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)

{

    IscsiLun *iscsilun = bs->opaque;

    struct IscsiTask iTask;

    struct unmap_list list;

    if (!is_byte_request_lun_aligned(offset, count, iscsilun)) {

        return -ENOTSUP;

    }

    if (!iscsilun->lbp.lbpu) {

        /* UNMAP is not supported by the target */

        return 0;

    }

    list.lba = offset / iscsilun->block_size;

    list.num = count / iscsilun->block_size;

    iscsi_co_init_iscsitask(iscsilun, &iTask);

retry:

    if (iscsi_unmap_task(iscsilun->iscsi, iscsilun->lun, 0, 0, &list, 1,

                         iscsi_co_generic_cb, &iTask) == NULL) {

        return -ENOMEM;

    }

    while (!iTask.complete) {

        iscsi_set_events(iscsilun);

        qemu_coroutine_yield();

    }

    if (iTask.task != NULL) {

        scsi_free_scsi_task(iTask.task);

        iTask.task = NULL;

    }

    if (iTask.do_retry) {

        iTask.complete = 0;

        goto retry;

    }

    if (iTask.status == SCSI_STATUS_CHECK_CONDITION) {

        /* the target might fail with a check condition if it

           is not happy with the alignment of the UNMAP request

           we silently fail in this case */

        return 0;

    }

    if (iTask.status != SCSI_STATUS_GOOD) {

        return iTask.err_code;

    }

    iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS,

                               count >> BDRV_SECTOR_BITS);

    return 0;

}


static ssize_t qio_channel_command_writev(QIOChannel *ioc,

                                          const struct iovec *iov,

                                          size_t niov,

                                          int *fds,

                                          size_t nfds,

                                          Error **errp)

{

    QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);

    ssize_t ret;

 retry:

    ret = writev(cioc->writefd, iov, niov);

    if (ret <= 0) {

        if (errno == EAGAIN ||

            errno == EWOULDBLOCK) {

            return QIO_CHANNEL_ERR_BLOCK;

        }

        if (errno == EINTR) {

            goto retry;

        }

        error_setg_errno(errp, errno, "%s",

                         "Unable to write to command");

        return -1;

    }

    return ret;

}


static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)

{

    stbuf->st_dev = 0;

    stbuf->st_ino = node->attr->inode;

    stbuf->st_mode = node->attr->mode;

    stbuf->st_nlink = node->attr->nlink;

    stbuf->st_uid = 0;

    stbuf->st_gid = 0;

    stbuf->st_rdev = 0;

    stbuf->st_size = 0;

    stbuf->st_blksize = 0;

    stbuf->st_blocks = 0;

    stbuf->st_atime = 0;

    stbuf->st_mtime = 0;

    stbuf->st_ctime = 0;

}


void cpu_exec_init(CPUState *env)

{

    CPUState **penv;

    int cpu_index;

#if defined(CONFIG_USER_ONLY)

    cpu_list_lock();

#endif

    env->next_cpu = NULL;

    penv = &first_cpu;

    cpu_index = 0;

    while (*penv != NULL) {

        penv = &(*penv)->next_cpu;

        cpu_index++;

    }

    env->cpu_index = cpu_index;

    env->numa_node = 0;

    TAILQ_INIT(&env->breakpoints);

    TAILQ_INIT(&env->watchpoints);

    *penv = env;

#if defined(CONFIG_USER_ONLY)

    cpu_list_unlock();

#endif

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

    vmstate_register(cpu_index, &vmstate_cpu_common, env);

    register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,

                    cpu_save, cpu_load, env);

#endif

}


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

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    SDHCIClass *k = SDHCI_CLASS(klass);

    dc->vmsd = &sdhci_vmstate;

    dc->props = sdhci_properties;

    dc->reset = sdhci_generic_reset;

    dc->realize = sdhci_realize;

    k->reset = sdhci_reset;

    k->mem_read = sdhci_read;

    k->mem_write = sdhci_write;

    k->send_command = sdhci_send_command;

    k->can_issue_command = sdhci_can_issue_command;

    k->data_transfer = sdhci_data_transfer;

    k->end_data_transfer = sdhci_end_transfer;

    k->do_sdma_single = sdhci_sdma_transfer_single_block;

    k->do_sdma_multi = sdhci_sdma_transfer_multi_blocks;

    k->do_adma = sdhci_do_adma;

    k->read_block_from_card = sdhci_read_block_from_card;

    k->write_block_to_card = sdhci_write_block_to_card;

    k->bdata_read = sdhci_read_dataport;

    k->bdata_write = sdhci_write_dataport;

}


static void ppc_heathrow_init(MachineState *machine)

{

    ram_addr_t ram_size = machine->ram_size;

    const char *cpu_model = machine->cpu_model;

    const char *kernel_filename = machine->kernel_filename;

    const char *kernel_cmdline = machine->kernel_cmdline;

    const char *initrd_filename = machine->initrd_filename;

    const char *boot_device = machine->boot_order;

    MemoryRegion *sysmem = get_system_memory();

    PowerPCCPU *cpu = NULL;

    CPUPPCState *env = NULL;

    char *filename;

    qemu_irq *pic, **heathrow_irqs;

    int linux_boot, i;

    MemoryRegion *ram = g_new(MemoryRegion, 1);

    MemoryRegion *bios = g_new(MemoryRegion, 1);

    MemoryRegion *isa = g_new(MemoryRegion, 1);

    uint32_t kernel_base, initrd_base, cmdline_base = 0;

    int32_t kernel_size, initrd_size;

    PCIBus *pci_bus;

    PCIDevice *macio;

    MACIOIDEState *macio_ide;

    DeviceState *dev;

    BusState *adb_bus;

    int bios_size;

    MemoryRegion *pic_mem;

    MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1);

    uint16_t ppc_boot_device;

    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];

    void *fw_cfg;

    linux_boot = (kernel_filename != NULL);

    /* init CPUs */

    if (cpu_model == NULL)

        cpu_model = "G3";

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

        cpu = cpu_ppc_init(cpu_model);

        if (cpu == NULL) {

            fprintf(stderr, "Unable to find PowerPC CPU definition\n");

            exit(1);

        }

        env = &cpu->env;

        /* Set time-base frequency to 16.6 Mhz */

        cpu_ppc_tb_init(env,  TBFREQ);

        qemu_register_reset(ppc_heathrow_reset, cpu);

    }

    /* allocate RAM */

    if (ram_size > (2047 << 20)) {

        fprintf(stderr,

                "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n",

                ((unsigned int)ram_size / (1 << 20)));

        exit(1);

    }

    memory_region_allocate_system_memory(ram, NULL, "ppc_heathrow.ram",

                                         ram_size);

    memory_region_add_subregion(sysmem, 0, ram);

    /* allocate and load BIOS */

    memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE);

    vmstate_register_ram_global(bios);

    if (bios_name == NULL)

        bios_name = PROM_FILENAME;

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);

    memory_region_set_readonly(bios, true);

    memory_region_add_subregion(sysmem, PROM_ADDR, bios);

    /* Load OpenBIOS (ELF) */

    if (filename) {

        bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,

                             1, ELF_MACHINE, 0);

        g_free(filename);

    } else {

        bios_size = -1;

    }

    if (bios_size < 0 || bios_size > BIOS_SIZE) {

        hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name);

        exit(1);

    }

    if (linux_boot) {

        uint64_t lowaddr = 0;

        int bswap_needed;

#ifdef BSWAP_NEEDED

        bswap_needed = 1;

#else

        bswap_needed = 0;

#endif

        kernel_base = KERNEL_LOAD_ADDR;

        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,

                               NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);

        if (kernel_size < 0)

            kernel_size = load_aout(kernel_filename, kernel_base,

                                    ram_size - kernel_base, bswap_needed,

                                    TARGET_PAGE_SIZE);

        if (kernel_size < 0)

            kernel_size = load_image_targphys(kernel_filename,

                                              kernel_base,

                                              ram_size - kernel_base);

        if (kernel_size < 0) {

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

                      kernel_filename);

            exit(1);

        }

        /* load initrd */

        if (initrd_filename) {

            initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);

            initrd_size = load_image_targphys(initrd_filename, initrd_base,

                                              ram_size - initrd_base);

            if (initrd_size < 0) {

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

                         initrd_filename);

                exit(1);

            }

            cmdline_base = round_page(initrd_base + initrd_size);

        } else {

            initrd_base = 0;

            initrd_size = 0;

            cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);

        }

        ppc_boot_device = 'm';

    } else {

        kernel_base = 0;

        kernel_size = 0;

        initrd_base = 0;

        initrd_size = 0;

        ppc_boot_device = '\0';

        for (i = 0; boot_device[i] != '\0'; i++) {

            /* TOFIX: for now, the second IDE channel is not properly

             *        used by OHW. The Mac floppy disk are not emulated.

             *        For now, OHW cannot boot from the network.

             */

#if 0

            if (boot_device[i] >= 'a' && boot_device[i] <= 'f') {

                ppc_boot_device = boot_device[i];

                break;

            }

#else

            if (boot_device[i] >= 'c' && boot_device[i] <= 'd') {

                ppc_boot_device = boot_device[i];

                break;

            }

#endif

        }

        if (ppc_boot_device == '\0') {

            fprintf(stderr, "No valid boot device for G3 Beige machine\n");

            exit(1);

        }

    }

    /* Register 2 MB of ISA IO space */

    memory_region_init_alias(isa, NULL, "isa_mmio",

                             get_system_io(), 0, 0x00200000);

    memory_region_add_subregion(sysmem, 0xfe000000, isa);

    /* XXX: we register only 1 output pin for heathrow PIC */

    heathrow_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));

    heathrow_irqs[0] =

        g_malloc0(smp_cpus * sizeof(qemu_irq) * 1);

    /* Connect the heathrow PIC outputs to the 6xx bus */

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

        switch (PPC_INPUT(env)) {

        case PPC_FLAGS_INPUT_6xx:

            heathrow_irqs[i] = heathrow_irqs[0] + (i * 1);

            heathrow_irqs[i][0] =

                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];

            break;

        default:

            hw_error("Bus model not supported on OldWorld Mac machine\n");

        }

    }

    /* init basic PC hardware */

    if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {

        hw_error("Only 6xx bus is supported on heathrow machine\n");

    }

    pic = heathrow_pic_init(&pic_mem, 1, heathrow_irqs);

    pci_bus = pci_grackle_init(0xfec00000, pic,

                               get_system_memory(),

                               get_system_io());

    pci_vga_init(pci_bus);

    escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0],

                               serial_hds[1], ESCC_CLOCK, 4);

    memory_region_init_alias(escc_bar, NULL, "escc-bar",

                             escc_mem, 0, memory_region_size(escc_mem));

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

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

    ide_drive_get(hd, MAX_IDE_BUS);

    macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO);

    dev = DEVICE(macio);

    qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */

    qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE-0 */

    qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */

    qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */

    qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */

    macio_init(macio, pic_mem, escc_bar);

    macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),

                                                        "ide[0]"));

    macio_ide_init_drives(macio_ide, hd);

    macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),

                                                        "ide[1]"));

    macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]);

    dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda"));

    adb_bus = qdev_get_child_bus(dev, "adb.0");

    dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD);

    qdev_init_nofail(dev);

    dev = qdev_create(adb_bus, TYPE_ADB_MOUSE);

    qdev_init_nofail(dev);

    if (usb_enabled(false)) {

        pci_create_simple(pci_bus, -1, "pci-ohci");

    }

    if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)

        graphic_depth = 15;

    /* No PCI init: the BIOS will do it */

    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);

    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);

    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);

    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);

    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW);

    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);

    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);

    if (kernel_cmdline) {

        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);

        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);

    } else {

        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);

    }

    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base);

    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);

    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device);

    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width);

    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);

    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);

    fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled());

    if (kvm_enabled()) {

#ifdef CONFIG_KVM

        uint8_t *hypercall;

        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());

        hypercall = g_malloc(16);

        kvmppc_get_hypercall(env, hypercall, 16);

        fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);

        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());

#endif

    } else {

        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ);

    }

    /* Mac OS X requires a "known good" clock-frequency value; pass it one. */

    fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ);

    fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ);

    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);

}


static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb,

                                 int ctb_addr_ts)

{

    HEVCLocalContext *lc  = &s->HEVClc;

    int ctb_size          = 1 << s->ps.sps->log2_ctb_size;

    int ctb_addr_rs       = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts];

    int ctb_addr_in_slice = ctb_addr_rs - s->sh.slice_addr;

    s->tab_slice_address[ctb_addr_rs] = s->sh.slice_addr;

    if (s->ps.pps->entropy_coding_sync_enabled_flag) {

        if (x_ctb == 0 && (y_ctb & (ctb_size - 1)) == 0)

            lc->first_qp_group = 1;

        lc->end_of_tiles_x = s->ps.sps->width;

    } else if (s->ps.pps->tiles_enabled_flag) {

        if (ctb_addr_ts && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[ctb_addr_ts - 1]) {

            int idxX = s->ps.pps->col_idxX[x_ctb >> s->ps.sps->log2_ctb_size];

            lc->start_of_tiles_x = x_ctb;

            lc->end_of_tiles_x   = x_ctb + (s->ps.pps->column_width[idxX] << s->ps.sps->log2_ctb_size);

            lc->first_qp_group   = 1;

        }

    } else {

        lc->end_of_tiles_x = s->ps.sps->width;

    }

    lc->end_of_tiles_y = FFMIN(y_ctb + ctb_size, s->ps.sps->height);

    lc->boundary_flags = 0;

    if (s->ps.pps->tiles_enabled_flag) {

        if (x_ctb > 0 && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - 1]])

            lc->boundary_flags |= BOUNDARY_LEFT_TILE;

        if (x_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - 1])

            lc->boundary_flags |= BOUNDARY_LEFT_SLICE;

        if (y_ctb > 0 && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - s->ps.sps->ctb_width]])

            lc->boundary_flags |= BOUNDARY_UPPER_TILE;

        if (y_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - s->ps.sps->ctb_width])

            lc->boundary_flags |= BOUNDARY_UPPER_SLICE;

    } else {

        if (!ctb_addr_in_slice > 0)

            lc->boundary_flags |= BOUNDARY_LEFT_SLICE;

        if (ctb_addr_in_slice < s->ps.sps->ctb_width)

            lc->boundary_flags |= BOUNDARY_UPPER_SLICE;

    }

    lc->ctb_left_flag = ((x_ctb > 0) && (ctb_addr_in_slice > 0) && !(lc->boundary_flags & BOUNDARY_LEFT_TILE));

    lc->ctb_up_flag   = ((y_ctb > 0) && (ctb_addr_in_slice >= s->ps.sps->ctb_width) && !(lc->boundary_flags & BOUNDARY_UPPER_TILE));

    lc->ctb_up_right_flag = ((y_ctb > 0)  && (ctb_addr_in_slice+1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs+1 - s->ps.sps->ctb_width]]));

    lc->ctb_up_left_flag = ((x_ctb > 0) && (y_ctb > 0)  && (ctb_addr_in_slice-1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1 - s->ps.sps->ctb_width]]));

}


static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)

{

    SCSIDevice *dev = SCSI_DEVICE(qdev);

    if (dev->vmsentry) {

        qemu_del_vm_change_state_handler(dev->vmsentry);

    }

    scsi_device_unrealize(dev, errp);

}


static void xen_set_memory(struct MemoryListener *listener,

                           MemoryRegionSection *section,

                           bool add)

{

    XenIOState *state = container_of(listener, XenIOState, memory_listener);

    hwaddr start_addr = section->offset_within_address_space;

    ram_addr_t size = int128_get64(section->size);

    bool log_dirty = memory_region_is_logging(section->mr);

    hvmmem_type_t mem_type;

    if (!memory_region_is_ram(section->mr)) {

        return;

    }

    if (!(section->mr != &ram_memory

          && ( (log_dirty && add) || (!log_dirty && !add)))) {

        return;

    }

    trace_xen_client_set_memory(start_addr, size, log_dirty);

    start_addr &= TARGET_PAGE_MASK;

    size = TARGET_PAGE_ALIGN(size);

    if (add) {

        if (!memory_region_is_rom(section->mr)) {

            xen_add_to_physmap(state, start_addr, size,

                               section->mr, section->offset_within_region);

        } else {

            mem_type = HVMMEM_ram_ro;

            if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,

                                    start_addr >> TARGET_PAGE_BITS,

                                    size >> TARGET_PAGE_BITS)) {

                DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",

                        start_addr);

            }

        }

    } else {

        if (xen_remove_from_physmap(state, start_addr, size) < 0) {

            DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);

        }

    }

}


opts_check_list(Visitor *v, Error **errp)

{

    /*

     * FIXME should set error when unvisited elements remain.  Mostly

     * harmless, as the generated visits always visit all elements.

     */

}


static int vorbis_packet(AVFormatContext *s, int idx)

{

    struct ogg *ogg = s->priv_data;

    struct ogg_stream *os = ogg->streams + idx;

    struct oggvorbis_private *priv = os->private;

    int duration;

    /* first packet handling

       here we parse the duration of each packet in the first page and compare

       the total duration to the page granule to find the encoder delay and

       set the first timestamp */

    if (!os->lastpts) {

        int seg;

        uint8_t *last_pkt = os->buf + os->pstart;

        uint8_t *next_pkt = last_pkt;

        int first_duration = 0;

        avpriv_vorbis_parse_reset(&priv->vp);

        duration = 0;

        for (seg = 0; seg < os->nsegs; seg++) {

            if (os->segments[seg] < 255) {

                int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);

                if (d < 0) {

                    duration = os->granule;

                    break;

                }

                if (!duration)

                    first_duration = d;

                duration += d;

                last_pkt = next_pkt + os->segments[seg];

            }

            next_pkt += os->segments[seg];

        }

        os->lastpts = os->lastdts   = os->granule - duration;

        s->streams[idx]->start_time = os->lastpts + first_duration;

        if (s->streams[idx]->duration)

            s->streams[idx]->duration -= s->streams[idx]->start_time;

        s->streams[idx]->cur_dts    = AV_NOPTS_VALUE;

        priv->final_pts             = AV_NOPTS_VALUE;

        avpriv_vorbis_parse_reset(&priv->vp);

    }

    /* parse packet duration */

    if (os->psize > 0) {

        duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1);

        if (duration <= 0) {

            os->pflags |= AV_PKT_FLAG_CORRUPT;

            return 0;

        }

        os->pduration = duration;

    }

    /* final packet handling

       here we save the pts of the first packet in the final page, sum up all

       packet durations in the final page except for the last one, and compare

       to the page granule to find the duration of the final packet */

    if (os->flags & OGG_FLAG_EOS) {

        if (os->lastpts != AV_NOPTS_VALUE) {

            priv->final_pts = os->lastpts;

            priv->final_duration = 0;

        }

        if (os->segp == os->nsegs)

            os->pduration = os->granule - priv->final_pts - priv->final_duration;

        priv->final_duration += os->pduration;

    }

    return 0;

}


static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)

{

    SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);

    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);

    int32_t len;

    uint8_t command;

    command = buf[0];

    if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {

        scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));

    }

    switch (command) {

    case READ_6:

    case READ_10:

    case READ_12:

    case READ_16:

        len = r->req.cmd.xfer / s->qdev.blocksize;

        DPRINTF("Read (sector %" PRId64 ", count %d)\n", r->req.cmd.lba, len);

        if (r->req.cmd.buf[1] & 0xe0) {

            goto illegal_request;

        }

        if (r->req.cmd.lba > s->qdev.max_lba) {

            goto illegal_lba;

        }

        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);

        r->sector_count = len * (s->qdev.blocksize / 512);

        break;

    case VERIFY_10:

    case VERIFY_12:

    case VERIFY_16:

    case WRITE_6:

    case WRITE_10:

    case WRITE_12:

    case WRITE_16:

    case WRITE_VERIFY_10:

    case WRITE_VERIFY_12:

    case WRITE_VERIFY_16:

        len = r->req.cmd.xfer / s->qdev.blocksize;

        DPRINTF("Write %s(sector %" PRId64 ", count %d)\n",

                (command & 0xe) == 0xe ? "And Verify " : "",

                r->req.cmd.lba, len);

        if (r->req.cmd.buf[1] & 0xe0) {

            goto illegal_request;

        }

        if (r->req.cmd.lba > s->qdev.max_lba) {

            goto illegal_lba;

        }

        r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);

        r->sector_count = len * (s->qdev.blocksize / 512);

        break;

    default:

        abort();

    illegal_lba:

        scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));

    }

    if (r->sector_count == 0) {

        scsi_req_complete(&r->req, GOOD);

    }

    assert(r->iov.iov_len == 0);

    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {

        return -r->sector_count * 512;

    } else {

        return r->sector_count * 512;

    }

}


static void coroutine_fn mirror_run(void *opaque)

{

    MirrorBlockJob *s = opaque;

    MirrorExitData *data;

    BlockDriverState *bs = s->common.bs;

    int64_t sector_num, end, sectors_per_chunk, length;

    uint64_t last_pause_ns;

    BlockDriverInfo bdi;

    char backing_filename[1024];

    int ret = 0;

    int n;

    if (block_job_is_cancelled(&s->common)) {

        goto immediate_exit;

    }

    s->bdev_length = bdrv_getlength(bs);

    if (s->bdev_length < 0) {

        ret = s->bdev_length;

        goto immediate_exit;

    } else if (s->bdev_length == 0) {

        /* Report BLOCK_JOB_READY and wait for complete. */

        block_job_event_ready(&s->common);

        s->synced = true;

        while (!block_job_is_cancelled(&s->common) && !s->should_complete) {

            block_job_yield(&s->common);

        }

        s->common.cancelled = false;

        goto immediate_exit;

    }

    length = DIV_ROUND_UP(s->bdev_length, s->granularity);

    s->in_flight_bitmap = bitmap_new(length);

    /* If we have no backing file yet in the destination, we cannot let

     * the destination do COW.  Instead, we copy sectors around the

     * dirty data if needed.  We need a bitmap to do that.

     */

    bdrv_get_backing_filename(s->target, backing_filename,

                              sizeof(backing_filename));

    if (backing_filename[0] && !s->target->backing_hd) {

        ret = bdrv_get_info(s->target, &bdi);

        if (ret < 0) {

            goto immediate_exit;

        }

        if (s->granularity < bdi.cluster_size) {

            s->buf_size = MAX(s->buf_size, bdi.cluster_size);

            s->cow_bitmap = bitmap_new(length);

        }

    }

    end = s->bdev_length / BDRV_SECTOR_SIZE;

    s->buf = qemu_try_blockalign(bs, s->buf_size);

    if (s->buf == NULL) {

        ret = -ENOMEM;

        goto immediate_exit;

    }

    sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;

    mirror_free_init(s);

    if (!s->is_none_mode) {

        /* First part, loop on the sectors and initialize the dirty bitmap.  */

        BlockDriverState *base = s->base;

        for (sector_num = 0; sector_num < end; ) {

            int64_t next = (sector_num | (sectors_per_chunk - 1)) + 1;

            ret = bdrv_is_allocated_above(bs, base,

                                          sector_num, next - sector_num, &n);

            if (ret < 0) {

                goto immediate_exit;

            }

            assert(n > 0);

            if (ret == 1) {

                bdrv_set_dirty(bs, sector_num, n);

                sector_num = next;

            } else {

                sector_num += n;

            }

        }

    }

    bdrv_dirty_iter_init(bs, s->dirty_bitmap, &s->hbi);

    last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);

    for (;;) {

        uint64_t delay_ns = 0;

        int64_t cnt;

        bool should_complete;

        if (s->ret < 0) {

            ret = s->ret;

            goto immediate_exit;

        }

        cnt = bdrv_get_dirty_count(bs, s->dirty_bitmap);

        /* s->common.offset contains the number of bytes already processed so

         * far, cnt is the number of dirty sectors remaining and

         * s->sectors_in_flight is the number of sectors currently being

         * processed; together those are the current total operation length */

        s->common.len = s->common.offset +

                        (cnt + s->sectors_in_flight) * BDRV_SECTOR_SIZE;

        /* Note that even when no rate limit is applied we need to yield

         * periodically with no pending I/O so that qemu_aio_flush() returns.

         * We do so every SLICE_TIME nanoseconds, or when there is an error,

         * or when the source is clean, whichever comes first.

         */

        if (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - last_pause_ns < SLICE_TIME &&

            s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {

            if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 ||

                (cnt == 0 && s->in_flight > 0)) {

                trace_mirror_yield(s, s->in_flight, s->buf_free_count, cnt);

                qemu_coroutine_yield();

                continue;

            } else if (cnt != 0) {

                delay_ns = mirror_iteration(s);

                if (delay_ns == 0) {

                    continue;

                }

            }

        }

        should_complete = false;

        if (s->in_flight == 0 && cnt == 0) {

            trace_mirror_before_flush(s);

            ret = bdrv_flush(s->target);

            if (ret < 0) {

                if (mirror_error_action(s, false, -ret) ==

                    BLOCK_ERROR_ACTION_REPORT) {

                    goto immediate_exit;

                }

            } else {

                /* We're out of the streaming phase.  From now on, if the job

                 * is cancelled we will actually complete all pending I/O and

                 * report completion.  This way, block-job-cancel will leave

                 * the target in a consistent state.

                 */

                if (!s->synced) {

                    block_job_event_ready(&s->common);

                    s->synced = true;

                }

                should_complete = s->should_complete ||

                    block_job_is_cancelled(&s->common);

                cnt = bdrv_get_dirty_count(bs, s->dirty_bitmap);

            }

        }

        if (cnt == 0 && should_complete) {

            /* The dirty bitmap is not updated while operations are pending.

             * If we're about to exit, wait for pending operations before

             * calling bdrv_get_dirty_count(bs), or we may exit while the

             * source has dirty data to copy!

             *

             * Note that I/O can be submitted by the guest while

             * mirror_populate runs.

             */

            trace_mirror_before_drain(s, cnt);

            bdrv_drain(bs);

            cnt = bdrv_get_dirty_count(bs, s->dirty_bitmap);

        }

        ret = 0;

        trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);

        if (!s->synced) {

            block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);

            if (block_job_is_cancelled(&s->common)) {

                break;

            }

        } else if (!should_complete) {

            delay_ns = (s->in_flight == 0 && cnt == 0 ? SLICE_TIME : 0);

            block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);

        } else if (cnt == 0) {

            /* The two disks are in sync.  Exit and report successful

             * completion.

             */

            assert(QLIST_EMPTY(&bs->tracked_requests));

            s->common.cancelled = false;

            break;

        }

        last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);

    }

immediate_exit:

    if (s->in_flight > 0) {

        /* We get here only if something went wrong.  Either the job failed,

         * or it was cancelled prematurely so that we do not guarantee that

         * the target is a copy of the source.

         */

        assert(ret < 0 || (!s->synced && block_job_is_cancelled(&s->common)));

        mirror_drain(s);

    }

    assert(s->in_flight == 0);

    qemu_vfree(s->buf);

    g_free(s->cow_bitmap);

    g_free(s->in_flight_bitmap);

    bdrv_release_dirty_bitmap(bs, s->dirty_bitmap);

    bdrv_iostatus_disable(s->target);

    data = g_malloc(sizeof(*data));

    data->ret = ret;

    block_job_defer_to_main_loop(&s->common, mirror_exit, data);

}


int object_property_get_enum(Object *obj, const char *name,

                             const char *strings[], Error **errp)

{

    StringOutputVisitor *sov;

    StringInputVisitor *siv;

    int ret;

    sov = string_output_visitor_new(false);

    object_property_get(obj, string_output_get_visitor(sov), name, errp);

    siv = string_input_visitor_new(string_output_get_string(sov));

    string_output_visitor_cleanup(sov);

    visit_type_enum(string_input_get_visitor(siv),

                    &ret, strings, NULL, name, errp);

    string_input_visitor_cleanup(siv);

    return ret;

}


int ff_vaapi_render_picture(FFVAContext *vactx, VASurfaceID surface)

{

    VABufferID va_buffers[3];

    unsigned int n_va_buffers = 0;

    if (!vactx->pic_param_buf_id)

        return 0;

    vaUnmapBuffer(vactx->display, vactx->pic_param_buf_id);

    va_buffers[n_va_buffers++] = vactx->pic_param_buf_id;

    if (vactx->iq_matrix_buf_id) {

        vaUnmapBuffer(vactx->display, vactx->iq_matrix_buf_id);

        va_buffers[n_va_buffers++] = vactx->iq_matrix_buf_id;

    }

    if (vactx->bitplane_buf_id) {

        vaUnmapBuffer(vactx->display, vactx->bitplane_buf_id);

        va_buffers[n_va_buffers++] = vactx->bitplane_buf_id;

    }

    if (vaBeginPicture(vactx->display, vactx->context_id,

                       surface) != VA_STATUS_SUCCESS)

        return -1;

    if (vaRenderPicture(vactx->display, vactx->context_id,

                        va_buffers, n_va_buffers) != VA_STATUS_SUCCESS)

        return -1;

    if (vaRenderPicture(vactx->display, vactx->context_id,

                        vactx->slice_buf_ids,

                        vactx->n_slice_buf_ids) != VA_STATUS_SUCCESS)

        return -1;

    if (vaEndPicture(vactx->display, vactx->context_id) != VA_STATUS_SUCCESS)

        return -1;

    return 0;

}


static void loop_filter(H264Context *h){

    MpegEncContext * const s = &h->s;

    uint8_t  *dest_y, *dest_cb, *dest_cr;

    int linesize, uvlinesize, mb_x, mb_y;

    const int end_mb_y= s->mb_y + FRAME_MBAFF;

    const int old_slice_type= h->slice_type;

    if(h->deblocking_filter) {

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

            for(mb_y=end_mb_y - FRAME_MBAFF; mb_y<= end_mb_y; mb_y++){

                int list, mb_xy, mb_type;

                mb_xy = h->mb_xy = mb_x + mb_y*s->mb_stride;

                h->slice_num= h->slice_table[mb_xy];

                mb_type= s->current_picture.mb_type[mb_xy];

                h->list_count= h->list_counts[mb_xy];

                if(FRAME_MBAFF)

                    h->mb_mbaff = h->mb_field_decoding_flag = !!IS_INTERLACED(mb_type);

                s->mb_x= mb_x;

                s->mb_y= mb_y;

                dest_y  = s->current_picture.data[0] + (mb_x + mb_y * s->linesize  ) * 16;

                dest_cb = s->current_picture.data[1] + (mb_x + mb_y * s->uvlinesize) * 8;

                dest_cr = s->current_picture.data[2] + (mb_x + mb_y * s->uvlinesize) * 8;

                    //FIXME simplify above

                if (MB_FIELD) {

                    linesize   = h->mb_linesize   = s->linesize * 2;

                    uvlinesize = h->mb_uvlinesize = s->uvlinesize * 2;

                    if(mb_y&1){ //FIXME move out of this function?

                        dest_y -= s->linesize*15;

                        dest_cb-= s->uvlinesize*7;

                        dest_cr-= s->uvlinesize*7;

                    }

                } else {

                    linesize   = h->mb_linesize   = s->linesize;

                    uvlinesize = h->mb_uvlinesize = s->uvlinesize;

                }

                backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0);

                if(fill_filter_caches(h, mb_type) < 0)

                    continue;

                h->chroma_qp[0] = get_chroma_qp(h, 0, s->current_picture.qscale_table[mb_xy]);

                h->chroma_qp[1] = get_chroma_qp(h, 1, s->current_picture.qscale_table[mb_xy]);

                if (FRAME_MBAFF) {

                    ff_h264_filter_mb     (h, mb_x, mb_y, dest_y, dest_cb, dest_cr, linesize, uvlinesize);

                } else {

                    ff_h264_filter_mb_fast(h, mb_x, mb_y, dest_y, dest_cb, dest_cr, linesize, uvlinesize);

                }

            }

        }

    }

    h->slice_type= old_slice_type;

    s->mb_x= 0;

    s->mb_y= end_mb_y - FRAME_MBAFF;

}


static int mov_write_tfhd_tag(AVIOContext *pb, MOVTrack *track,

                              int64_t moof_offset)

{

    int64_t pos = avio_tell(pb);

    uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION |

                     MOV_TFHD_BASE_DATA_OFFSET;

    if (!track->entry) {

        flags |= MOV_TFHD_DURATION_IS_EMPTY;

    } else {

        flags |= MOV_TFHD_DEFAULT_FLAGS;

    }

    /* Don't set a default sample size, the silverlight player refuses

     * to play files with that set. Don't set a default sample duration,

     * WMP freaks out if it is set. */

    if (track->mode == MODE_ISM)

        flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION);

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

    ffio_wfourcc(pb, "tfhd");

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

    avio_wb24(pb, flags);

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

    if (flags & MOV_TFHD_BASE_DATA_OFFSET)

        avio_wb64(pb, moof_offset);

    if (flags & MOV_TFHD_DEFAULT_DURATION) {

        track->default_duration = get_cluster_duration(track, 0);

        avio_wb32(pb, track->default_duration);

    }

    if (flags & MOV_TFHD_DEFAULT_SIZE) {

        track->default_size = track->entry ? track->cluster[0].size : 1;

        avio_wb32(pb, track->default_size);

    } else

        track->default_size = -1;

    if (flags & MOV_TFHD_DEFAULT_FLAGS) {

        track->default_sample_flags =

            track->enc->codec_type == AVMEDIA_TYPE_VIDEO ?

            (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :

            MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;

        avio_wb32(pb, track->default_sample_flags);

    }

    return update_size(pb, pos);

}


static int normalize_samples(AC3EncodeContext *s)

{

    int v = 14 - log2_tab(s, s->windowed_samples, AC3_WINDOW_SIZE);

    lshift_tab(s->windowed_samples, AC3_WINDOW_SIZE, v);

    return v - 9;

}


uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)

{

    int r = sclp_service_call(env, r1, r2);

    if (r < 0) {

        program_interrupt(env, -r, 4);

        return 0;

    }

    return r;

}


static void test_query_cpus(const void *data)

{

    char *cli;

    QDict *resp;

    QList *cpus;

    const QObject *e;

    cli = make_cli(data, "-smp 8 -numa node,cpus=0-3 -numa node,cpus=4-7");

    qtest_start(cli);

    cpus = get_cpus(&resp);

    g_assert(cpus);

    while ((e = qlist_pop(cpus))) {

        QDict *cpu, *props;

        int64_t cpu_idx, node;

        cpu = qobject_to_qdict(e);

        g_assert(qdict_haskey(cpu, "CPU"));

        g_assert(qdict_haskey(cpu, "props"));

        cpu_idx = qdict_get_int(cpu, "CPU");

        props = qdict_get_qdict(cpu, "props");

        g_assert(qdict_haskey(props, "node-id"));

        node = qdict_get_int(props, "node-id");

        if (cpu_idx >= 0 && cpu_idx < 4) {

            g_assert_cmpint(node, ==, 0);

        } else {

            g_assert_cmpint(node, ==, 1);

        }

    }

    QDECREF(resp);

    qtest_end();

    g_free(cli);

}


int virtio_scsi_common_exit(VirtIOSCSICommon *vs)

{

    VirtIODevice *vdev = VIRTIO_DEVICE(vs);

    g_free(vs->cmd_vqs);

    virtio_cleanup(vdev);

    return 0;

}


static int decode_subframe_fixed(FLACContext *s, int32_t *decoded,

                                 int pred_order, int bps)

{

    const int blocksize = s->blocksize;

    unsigned av_uninit(a), av_uninit(b), av_uninit(c), av_uninit(d);

    int i;

    int ret;

    /* warm up samples */

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

        decoded[i] = get_sbits_long(&s->gb, bps);

    }

    if ((ret = decode_residuals(s, decoded, pred_order)) < 0)

        return ret;

    if (pred_order > 0)

        a = decoded[pred_order-1];

    if (pred_order > 1)

        b = a - decoded[pred_order-2];

    if (pred_order > 2)

        c = b - decoded[pred_order-2] + decoded[pred_order-3];

    if (pred_order > 3)

        d = c - decoded[pred_order-2] + 2*decoded[pred_order-3] - decoded[pred_order-4];

    switch (pred_order) {

    case 0:

        break;

    case 1:

        for (i = pred_order; i < blocksize; i++)

            decoded[i] = a += decoded[i];

        break;

    case 2:

        for (i = pred_order; i < blocksize; i++)

            decoded[i] = a += b += decoded[i];

        break;

    case 3:

        for (i = pred_order; i < blocksize; i++)

            decoded[i] = a += b += c += decoded[i];

        break;

    case 4:

        for (i = pred_order; i < blocksize; i++)

            decoded[i] = a += b += c += d += decoded[i];

        break;

    default:

        av_log(s->avctx, AV_LOG_ERROR, "illegal pred order %d\n", pred_order);

        return AVERROR_INVALIDDATA;

    }

    return 0;

}


static int add_tonal_components(float *spectrum, int num_components,

                                TonalComponent *components)

{

    int i, j, last_pos = -1;

    float *input, *output;

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

        last_pos = FFMAX(components[i].pos + components[i].num_coefs, last_pos);

        input    = components[i].coef;

        output   = &spectrum[components[i].pos];

        for (j = 0; j < components[i].num_coefs; j++)

            output[i] += input[i];

    }

    return last_pos;

}


static int qemu_rdma_write_flush(QEMUFile *f, RDMAContext *rdma)

{

    int ret;

    if (!rdma->current_length) {

        return 0;

    }

    ret = qemu_rdma_write_one(f, rdma,

            rdma->current_index, rdma->current_addr, rdma->current_length);

    if (ret < 0) {

        return ret;

    }

    if (ret == 0) {

        rdma->nb_sent++;

        DDDPRINTF("sent total: %d\n", rdma->nb_sent);

    }

    rdma->current_length = 0;

    rdma->current_addr = 0;

    return 0;

}


Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
        unsigned long ram_size)
{
    int i, n;
    Exynos4210State *s = g_new(Exynos4210State, 1);
    qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
    unsigned long mem_size;
    DeviceState *dev;
    SysBusDevice *busdev;
    ObjectClass *cpu_oc;
    cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, "cortex-a9");
    assert(cpu_oc);
    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
        Object *cpuobj = object_new(object_class_get_name(cpu_oc));
        /* By default A9 CPUs have EL3 enabled.  This board does not currently
         * support EL3 so the CPU EL3 property is disabled before realization.
         */
        if (object_property_find(cpuobj, "has_el3", NULL)) {
            object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
        }
        s->cpu[n] = ARM_CPU(cpuobj);
        object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
                                "reset-cbar", &error_abort);
        object_property_set_bool(cpuobj, true, "realized", &error_fatal);
    }
    /*** IRQs ***/
    s->irq_table = exynos4210_init_irq(&s->irqs);
    /* IRQ Gate */
    for (i = 0; i < EXYNOS4210_NCPUS; i++) {
        dev = qdev_create(NULL, "exynos4210.irq_gate");
        qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
        qdev_init_nofail(dev);
        /* Get IRQ Gate input in gate_irq */
        for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
            gate_irq[i][n] = qdev_get_gpio_in(dev, n);
        }
        busdev = SYS_BUS_DEVICE(dev);
        /* Connect IRQ Gate output to CPU's IRQ line */
        sysbus_connect_irq(busdev, 0,
                           qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
    }
    /* Private memory region and Internal GIC */
    dev = qdev_create(NULL, "a9mpcore_priv");
    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
    qdev_init_nofail(dev);
    busdev = SYS_BUS_DEVICE(dev);
    sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
        sysbus_connect_irq(busdev, n, gate_irq[n][0]);
    }
    for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
        s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
    }
    /* Cache controller */
    sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
    /* External GIC */
    dev = qdev_create(NULL, "exynos4210.gic");
    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
    qdev_init_nofail(dev);
    busdev = SYS_BUS_DEVICE(dev);
    /* Map CPU interface */
    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
    /* Map Distributer interface */
    sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
        sysbus_connect_irq(busdev, n, gate_irq[n][1]);
    }
    for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
        s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
    }
    /* Internal Interrupt Combiner */
    dev = qdev_create(NULL, "exynos4210.combiner");
    qdev_init_nofail(dev);
    busdev = SYS_BUS_DEVICE(dev);
    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
        sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
    }
    exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
    sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
    /* External Interrupt Combiner */
    dev = qdev_create(NULL, "exynos4210.combiner");
    qdev_prop_set_uint32(dev, "external", 1);
    qdev_init_nofail(dev);
    busdev = SYS_BUS_DEVICE(dev);
    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
        sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
    }
    exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
    /* Initialize board IRQs. */
    exynos4210_init_board_irqs(&s->irqs);
    /*** Memory ***/
    /* Chip-ID and OMR */
    memory_region_init_io(&s->chipid_mem, NULL, &exynos4210_chipid_and_omr_ops,
        NULL, "exynos4210.chipid", sizeof(chipid_and_omr));
    memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
                                &s->chipid_mem);
    /* Internal ROM */
    memory_region_init_ram(&s->irom_mem, NULL, "exynos4210.irom",
                           EXYNOS4210_IROM_SIZE, &error_fatal);
    vmstate_register_ram_global(&s->irom_mem);
    memory_region_set_readonly(&s->irom_mem, true);
    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
                                &s->irom_mem);
    /* mirror of iROM */
    memory_region_init_alias(&s->irom_alias_mem, NULL, "exynos4210.irom_alias",
                             &s->irom_mem,
                             0,
                             EXYNOS4210_IROM_SIZE);
    memory_region_set_readonly(&s->irom_alias_mem, true);
    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR,
                                &s->irom_alias_mem);
    /* Internal RAM */
    memory_region_init_ram(&s->iram_mem, NULL, "exynos4210.iram",
                           EXYNOS4210_IRAM_SIZE, &error_fatal);
    vmstate_register_ram_global(&s->iram_mem);
    memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
                                &s->iram_mem);
    /* DRAM */
    mem_size = ram_size;
    if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
        memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1",
                mem_size - EXYNOS4210_DRAM_MAX_SIZE, &error_fatal);
        vmstate_register_ram_global(&s->dram1_mem);
        memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
                &s->dram1_mem);
        mem_size = EXYNOS4210_DRAM_MAX_SIZE;
    }
    memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size,
                           &error_fatal);
    vmstate_register_ram_global(&s->dram0_mem);
    memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
            &s->dram0_mem);
   /* PMU.
    * The only reason of existence at the moment is that secondary CPU boot
    * loader uses PMU INFORM5 register as a holding pen.
    */
    sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
    /* PWM */
    sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
                          s->irq_table[exynos4210_get_irq(22, 0)],
                          s->irq_table[exynos4210_get_irq(22, 1)],
                          s->irq_table[exynos4210_get_irq(22, 2)],
                          s->irq_table[exynos4210_get_irq(22, 3)],
                          s->irq_table[exynos4210_get_irq(22, 4)],
                          NULL);
    /* RTC */
    sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR,
                          s->irq_table[exynos4210_get_irq(23, 0)],
                          s->irq_table[exynos4210_get_irq(23, 1)],
                          NULL);
    /* Multi Core Timer */
    dev = qdev_create(NULL, "exynos4210.mct");
    qdev_init_nofail(dev);
    busdev = SYS_BUS_DEVICE(dev);
    for (n = 0; n < 4; n++) {
        /* Connect global timer interrupts to Combiner gpio_in */
        sysbus_connect_irq(busdev, n,
                s->irq_table[exynos4210_get_irq(1, 4 + n)]);
    }
    /* Connect local timer interrupts to Combiner gpio_in */
    sysbus_connect_irq(busdev, 4,
            s->irq_table[exynos4210_get_irq(51, 0)]);
    sysbus_connect_irq(busdev, 5,
            s->irq_table[exynos4210_get_irq(35, 3)]);
    sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR);
    /*** I2C ***/
    for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) {
        uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n;
        qemu_irq i2c_irq;
        if (n < 8) {
            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)];
        } else {
            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)];
        }
        dev = qdev_create(NULL, "exynos4210.i2c");
        qdev_init_nofail(dev);
        busdev = SYS_BUS_DEVICE(dev);
        sysbus_connect_irq(busdev, 0, i2c_irq);
        sysbus_mmio_map(busdev, 0, addr);
        s->i2c_if[n] = (I2CBus *)qdev_get_child_bus(dev, "i2c");
    }
    /*** UARTs ***/
    exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
                           EXYNOS4210_UART0_FIFO_SIZE, 0, NULL,
                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
    exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
                           EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
    exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
                           EXYNOS4210_UART2_FIFO_SIZE, 2, NULL,
                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
    exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
                           EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
    /*** Display controller (FIMD) ***/
    sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR,
            s->irq_table[exynos4210_get_irq(11, 0)],
            s->irq_table[exynos4210_get_irq(11, 1)],
            s->irq_table[exynos4210_get_irq(11, 2)],
            NULL);
    sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
            s->irq_table[exynos4210_get_irq(28, 3)]);
    return s;
}


static void *clone_func(void *arg)

{

    new_thread_info *info = arg;

    CPUArchState *env;

    CPUState *cpu;

    TaskState *ts;

    rcu_register_thread();

    env = info->env;

    cpu = ENV_GET_CPU(env);

    thread_cpu = cpu;

    ts = (TaskState *)cpu->opaque;

    info->tid = gettid();

    cpu->host_tid = info->tid;

    task_settid(ts);

    if (info->child_tidptr)

        put_user_u32(info->tid, info->child_tidptr);

    if (info->parent_tidptr)

        put_user_u32(info->tid, info->parent_tidptr);

    /* Enable signals.  */

    sigprocmask(SIG_SETMASK, &info->sigmask, NULL);

    /* Signal to the parent that we're ready.  */

    pthread_mutex_lock(&info->mutex);

    pthread_cond_broadcast(&info->cond);

    pthread_mutex_unlock(&info->mutex);

    /* Wait until the parent has finshed initializing the tls state.  */

    pthread_mutex_lock(&clone_lock);

    pthread_mutex_unlock(&clone_lock);

    cpu_loop(env);

    /* never exits */

    return NULL;

}


static inline void RENAME(yuv2rgb32_1)(SwsContext *c, const uint16_t *buf0,

                                       const uint16_t *ubuf0, const uint16_t *ubuf1,

                                       const uint16_t *vbuf0, const uint16_t *vbuf1,

                                       const uint16_t *abuf0, uint8_t *dest,

                                       int dstW, int uvalpha, enum PixelFormat dstFormat,

                                       int flags, int y)

{

    x86_reg uv_off = c->uv_off << 1;

    const uint16_t *buf1= buf0; //FIXME needed for RGB1/BGR1

    if (uvalpha < 2048) { // note this is not correct (shifts chrominance by 0.5 pixels) but it is a bit faster

        if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {

            __asm__ volatile(

                "mov %%"REG_b", "ESP_OFFSET"(%5)        \n\t"

                "mov        %4, %%"REG_b"               \n\t"

                "push %%"REG_BP"                        \n\t"

                YSCALEYUV2RGB1(%%REGBP, %5, %6)

                YSCALEYUV2RGB1_ALPHA(%%REGBP)

                WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6)

                "pop %%"REG_BP"                         \n\t"

                "mov "ESP_OFFSET"(%5), %%"REG_b"        \n\t"

                :: "c" (buf0), "d" (abuf0), "S" (ubuf0), "D" (ubuf1), "m" (dest),

                   "a" (&c->redDither), "m"(uv_off)

            );

        } else {

            __asm__ volatile(

                "mov %%"REG_b", "ESP_OFFSET"(%5)        \n\t"

                "mov        %4, %%"REG_b"               \n\t"

                "push %%"REG_BP"                        \n\t"

                YSCALEYUV2RGB1(%%REGBP, %5, %6)

                "pcmpeqd %%mm7, %%mm7                   \n\t"

                WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6)

                "pop %%"REG_BP"                         \n\t"

                "mov "ESP_OFFSET"(%5), %%"REG_b"        \n\t"

                :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest),

                   "a" (&c->redDither), "m"(uv_off)

            );

        }

    } else {

        if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {

            __asm__ volatile(

                "mov %%"REG_b", "ESP_OFFSET"(%5)        \n\t"

                "mov        %4, %%"REG_b"               \n\t"

                "push %%"REG_BP"                        \n\t"

                YSCALEYUV2RGB1b(%%REGBP, %5, %6)

                YSCALEYUV2RGB1_ALPHA(%%REGBP)

                WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6)

                "pop %%"REG_BP"                         \n\t"

                "mov "ESP_OFFSET"(%5), %%"REG_b"        \n\t"

                :: "c" (buf0), "d" (abuf0), "S" (ubuf0), "D" (ubuf1), "m" (dest),

                   "a" (&c->redDither), "m"(uv_off)

            );

        } else {

            __asm__ volatile(

                "mov %%"REG_b", "ESP_OFFSET"(%5)        \n\t"

                "mov        %4, %%"REG_b"               \n\t"

                "push %%"REG_BP"                        \n\t"

                YSCALEYUV2RGB1b(%%REGBP, %5, %6)

                "pcmpeqd %%mm7, %%mm7                   \n\t"

                WRITEBGR32(%%REGb, 8280(%5), %%REGBP, %%mm2, %%mm4, %%mm5, %%mm7, %%mm0, %%mm1, %%mm3, %%mm6)

                "pop %%"REG_BP"                         \n\t"

                "mov "ESP_OFFSET"(%5), %%"REG_b"        \n\t"

                :: "c" (buf0), "d" (buf1), "S" (ubuf0), "D" (ubuf1), "m" (dest),

                   "a" (&c->redDither), "m"(uv_off)

            );

        }

    }

}


QInt *qobject_to_qint(const QObject *obj)

{

    if (qobject_type(obj) != QTYPE_QINT)

        return NULL;

    return container_of(obj, QInt, base);

}


static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image)

{

    int compno;

    int x;

    int y;

    int *image_line;

    int frame_index;

    const int numcomps = image->numcomps;

    for (compno = 0; compno < numcomps; ++compno) {

        if (image->comps[compno].w > frame->linesize[0] / numcomps) {

            av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n");

            return 0;

        }

    }

    for (compno = 0; compno < numcomps; ++compno) {

        for (y = 0; y < avctx->height; ++y) {

            image_line = image->comps[compno].data + y * image->comps[compno].w;

            frame_index = y * frame->linesize[0] + compno;

            for (x = 0; x < avctx->width; ++x) {

                image_line[x] = frame->data[0][frame_index];

                frame_index += numcomps;

            }

            for (; x < image->comps[compno].w; ++x) {

                image_line[x] = image_line[x - 1];

            }

        }

        for (; y < image->comps[compno].h; ++y) {

            image_line = image->comps[compno].data + y * image->comps[compno].w;

            for (x = 0; x < image->comps[compno].w; ++x) {

                image_line[x] = image_line[x - image->comps[compno].w];

            }

        }

    }

    return 1;

}


static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr,

                             bool alloc_new)

{

    int i;

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

        if (!phb->msi_table[i].nvec) {

            break;

        }

        if (phb->msi_table[i].config_addr == config_addr) {

            return i;

        }

    }

    if ((i < SPAPR_MSIX_MAX_DEVS) && alloc_new) {

        trace_spapr_pci_msi("Allocating new MSI config", i, config_addr);

        return i;

    }

    return -1;

}


static void fdctrl_connect_drives(FDCtrl *fdctrl)

{

    unsigned int i;

    FDrive *drive;

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

        drive = &fdctrl->drives[i];

        fd_init(drive);

        fd_revalidate(drive);

        if (drive->bs) {

            bdrv_set_removable(drive->bs, 1);

        }

    }

}


static av_cold int decode_init(AVCodecContext *avctx)

{

    ASV1Context *const a = avctx->priv_data;

    const int scale      = avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2;

    int i;

    if (avctx->extradata_size < 1) {

        av_log(avctx, AV_LOG_ERROR, "No extradata provided\n");

        return AVERROR_INVALIDDATA;

    }

    ff_asv_common_init(avctx);

    ff_blockdsp_init(&a->bdsp, avctx);

    ff_idctdsp_init(&a->idsp, avctx);

    init_vlcs(a);

    ff_init_scantable(a->idsp.idct_permutation, &a->scantable, ff_asv_scantab);

    avctx->pix_fmt = AV_PIX_FMT_YUV420P;

    a->inv_qscale = avctx->extradata[0];

    if (a->inv_qscale == 0) {

        av_log(avctx, AV_LOG_ERROR, "illegal qscale 0\n");

        if (avctx->codec_id == AV_CODEC_ID_ASV1)

            a->inv_qscale = 6;

        else

            a->inv_qscale = 10;

    }

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

        int index = ff_asv_scantab[i];

        a->intra_matrix[i] = 64 * scale * ff_mpeg1_default_intra_matrix[index] /

                             a->inv_qscale;

    }

    return 0;

}


int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask,

                        const AVFrame *reference)

{

    int len, nb_components, i, h, v, predictor, point_transform;

    int index, id, ret;

    const int block_size = s->lossless ? 1 : 8;

    int ilv, prev_shift;

    if (!s->got_picture) {

        av_log(s->avctx, AV_LOG_WARNING,

                "Can not process SOS before SOF, skipping\n");

        return -1;

    }

    av_assert0(s->picture_ptr->data[0]);

    /* XXX: verify len field validity */

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

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

    if (nb_components == 0 || nb_components > MAX_COMPONENTS) {

        av_log(s->avctx, AV_LOG_ERROR,

               "decode_sos: nb_components (%d) unsupported\n", nb_components);

        return AVERROR_PATCHWELCOME;

    }

    if (len != 6 + 2 * nb_components) {

        av_log(s->avctx, AV_LOG_ERROR, "decode_sos: invalid len (%d)\n", len);

        return AVERROR_INVALIDDATA;

    }

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

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

        av_log(s->avctx, AV_LOG_DEBUG, "component: %d\n", id);

        /* find component index */

        for (index = 0; index < s->nb_components; index++)

            if (id == s->component_id[index])

                break;

        if (index == s->nb_components) {

            av_log(s->avctx, AV_LOG_ERROR,

                   "decode_sos: index(%d) out of components\n", index);

            return AVERROR_INVALIDDATA;

        }

        /* Metasoft MJPEG codec has Cb and Cr swapped */

        if (s->avctx->codec_tag == MKTAG('M', 'T', 'S', 'J')

            && nb_components == 3 && s->nb_components == 3 && i)

            index = 3 - i;

        if(nb_components == 3 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P)

            index = (i+2)%3;

        if(nb_components == 1 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P)

            index = (index+2)%3;

        s->comp_index[i] = index;

        s->nb_blocks[i] = s->h_count[index] * s->v_count[index];

        s->h_scount[i]  = s->h_count[index];

        s->v_scount[i]  = s->v_count[index];

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

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

        if (s->dc_index[i] <  0 || s->ac_index[i] < 0 ||

            s->dc_index[i] >= 4 || s->ac_index[i] >= 4)

            goto out_of_range;

        if (!s->vlcs[0][s->dc_index[i]].table || !(s->progressive ? s->vlcs[2][s->ac_index[0]].table : s->vlcs[1][s->ac_index[i]].table))

            goto out_of_range;

    }

    predictor = get_bits(&s->gb, 8);       /* JPEG Ss / lossless JPEG predictor /JPEG-LS NEAR */

    ilv = get_bits(&s->gb, 8);             /* JPEG Se / JPEG-LS ILV */

    if(s->avctx->codec_tag != AV_RL32("CJPG")){

        prev_shift      = get_bits(&s->gb, 4); /* Ah */

        point_transform = get_bits(&s->gb, 4); /* Al */

    }else

        prev_shift = point_transform = 0;

    if (nb_components > 1) {

        /* interleaved stream */

        s->mb_width  = (s->width  + s->h_max * block_size - 1) / (s->h_max * block_size);

        s->mb_height = (s->height + s->v_max * block_size - 1) / (s->v_max * block_size);

    } else if (!s->ls) { /* skip this for JPEG-LS */

        h = s->h_max / s->h_scount[0];

        v = s->v_max / s->v_scount[0];

        s->mb_width     = (s->width  + h * block_size - 1) / (h * block_size);

        s->mb_height    = (s->height + v * block_size - 1) / (v * block_size);

        s->nb_blocks[0] = 1;

        s->h_scount[0]  = 1;

        s->v_scount[0]  = 1;

    }

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

        av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d skip:%d %s comp:%d\n",

               s->lossless ? "lossless" : "sequential DCT", s->rgb ? "RGB" : "",

               predictor, point_transform, ilv, s->bits, s->mjpb_skiptosod,

               s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : ""), nb_components);

    /* mjpeg-b can have padding bytes between sos and image data, skip them */

    for (i = s->mjpb_skiptosod; i > 0; i--)

        skip_bits(&s->gb, 8);

next_field:

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

        s->last_dc[i] = 1024;

    if (s->lossless) {

        av_assert0(s->picture_ptr == &s->picture);

        if (CONFIG_JPEGLS_DECODER && s->ls) {

//            for () {

//            reset_ls_coding_parameters(s, 0);

            if ((ret = ff_jpegls_decode_picture(s, predictor,

                                                point_transform, ilv)) < 0)

                return ret;

        } else {

            if (s->rgb) {

                if ((ret = ljpeg_decode_rgb_scan(s, nb_components, predictor, point_transform)) < 0)

                    return ret;

            } else {

                if ((ret = ljpeg_decode_yuv_scan(s, predictor,

                                                 point_transform,

                                                 nb_components)) < 0)

                    return ret;

            }

        }

    } else {

        if (s->progressive && predictor) {

            av_assert0(s->picture_ptr == &s->picture);

            if ((ret = mjpeg_decode_scan_progressive_ac(s, predictor,

                                                        ilv, prev_shift,

                                                        point_transform)) < 0)

                return ret;

        } else {

            if ((ret = mjpeg_decode_scan(s, nb_components,

                                         prev_shift, point_transform,

                                         mb_bitmask, reference)) < 0)

                return ret;

        }

    }

    if (s->interlaced &&

        get_bits_left(&s->gb) > 32 &&

        show_bits(&s->gb, 8) == 0xFF) {

        GetBitContext bak = s->gb;

        align_get_bits(&bak);

        if (show_bits(&bak, 16) == 0xFFD1) {

            av_log(s->avctx, AV_LOG_DEBUG, "AVRn interlaced picture marker found\n");

            s->gb = bak;

            skip_bits(&s->gb, 16);

            s->bottom_field ^= 1;

            goto next_field;

        }

    }

    emms_c();

    return 0;

 out_of_range:

    av_log(s->avctx, AV_LOG_ERROR, "decode_sos: ac/dc index out of range\n");

    return AVERROR_INVALIDDATA;

}


static void do_video_out(AVFormatContext *s,

                         AVOutputStream *ost,

                         AVInputStream *ist,

                         AVFrame *in_picture,

                         int *frame_size, AVOutputStream *audio_sync)

{

    int nb_frames, i, ret;

    AVFrame *final_picture, *formatted_picture;

    AVFrame picture_format_temp, picture_crop_temp;

    static uint8_t *video_buffer= NULL;

    uint8_t *buf = NULL, *buf1 = NULL;

    AVCodecContext *enc, *dec;

    enum PixelFormat target_pixfmt;

#define VIDEO_BUFFER_SIZE (1024*1024)

    avcodec_get_frame_defaults(&picture_format_temp);

    avcodec_get_frame_defaults(&picture_crop_temp);

    enc = &ost->st->codec;

    dec = &ist->st->codec;

    /* by default, we output a single frame */

    nb_frames = 1;

    *frame_size = 0;

    if(sync_method){

        double vdelta;

        vdelta = ost->sync_ipts * enc->frame_rate / enc->frame_rate_base - ost->sync_opts;

        //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c

        if (vdelta < -1.1)

            nb_frames = 0;

        else if (vdelta > 1.1)

            nb_frames = 2;

//printf("vdelta:%f, ost->sync_opts:%lld, ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, ost->sync_ipts, nb_frames);

    }

    ost->sync_opts+= nb_frames;

    if (nb_frames <= 0)

        return;

    if (!video_buffer)

        video_buffer = av_malloc(VIDEO_BUFFER_SIZE);

    if (!video_buffer)

        return;

    /* convert pixel format if needed */

    target_pixfmt = ost->video_resample || ost->video_pad

        ? PIX_FMT_YUV420P : enc->pix_fmt;

    if (dec->pix_fmt != target_pixfmt) {

        int size;

        /* create temporary picture */

        size = avpicture_get_size(target_pixfmt, dec->width, dec->height);

        buf = av_malloc(size);

        if (!buf)

            return;

        formatted_picture = &picture_format_temp;

        avpicture_fill((AVPicture*)formatted_picture, buf, target_pixfmt, dec->width, dec->height);

        if (img_convert((AVPicture*)formatted_picture, target_pixfmt,

                        (AVPicture *)in_picture, dec->pix_fmt,

                        dec->width, dec->height) < 0) {

            if (verbose >= 0)

                fprintf(stderr, "pixel format conversion not handled\n");

            goto the_end;

        }

    } else {

        formatted_picture = in_picture;

    }

    /* XXX: resampling could be done before raw format conversion in

       some cases to go faster */

    /* XXX: only works for YUV420P */

    if (ost->video_resample) {

        final_picture = &ost->pict_tmp;

        img_resample(ost->img_resample_ctx, (AVPicture*)final_picture, (AVPicture*)formatted_picture);

        if (ost->padtop || ost->padbottom || ost->padleft || ost->padright) {

            fill_pad_region((AVPicture*)final_picture, enc->height, enc->width,

                    ost->padtop, ost->padbottom, ost->padleft, ost->padright,

                    padcolor);

        }

	if (enc->pix_fmt != PIX_FMT_YUV420P) {

            int size;

	    av_free(buf);

            /* create temporary picture */

            size = avpicture_get_size(enc->pix_fmt, enc->width, enc->height);

            buf = av_malloc(size);

            if (!buf)

                return;

            final_picture = &picture_format_temp;

            avpicture_fill((AVPicture*)final_picture, buf, enc->pix_fmt, enc->width, enc->height);

            if (img_convert((AVPicture*)final_picture, enc->pix_fmt,

                            (AVPicture*)&ost->pict_tmp, PIX_FMT_YUV420P,

                            enc->width, enc->height) < 0) {

                if (verbose >= 0)

                    fprintf(stderr, "pixel format conversion not handled\n");

                goto the_end;

            }

	}

    } else if (ost->video_crop) {

        picture_crop_temp.data[0] = formatted_picture->data[0] +

                (ost->topBand * formatted_picture->linesize[0]) + ost->leftBand;

        picture_crop_temp.data[1] = formatted_picture->data[1] +

                ((ost->topBand >> 1) * formatted_picture->linesize[1]) +

                (ost->leftBand >> 1);

        picture_crop_temp.data[2] = formatted_picture->data[2] +

                ((ost->topBand >> 1) * formatted_picture->linesize[2]) +

                (ost->leftBand >> 1);

        picture_crop_temp.linesize[0] = formatted_picture->linesize[0];

        picture_crop_temp.linesize[1] = formatted_picture->linesize[1];

        picture_crop_temp.linesize[2] = formatted_picture->linesize[2];

        final_picture = &picture_crop_temp;

    } else if (ost->video_pad) {

        final_picture = &ost->pict_tmp;

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

            uint8_t *optr, *iptr;

            int shift = (i == 0) ? 0 : 1;

            int y, yheight;

            /* set offset to start writing image into */

            optr = final_picture->data[i] + (((final_picture->linesize[i] *

                            ost->padtop) + ost->padleft) >> shift);

            iptr = formatted_picture->data[i];

            yheight = (enc->height - ost->padtop - ost->padbottom) >> shift;

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

                /* copy unpadded image row into padded image row */

                memcpy(optr, iptr, formatted_picture->linesize[i]);

                optr += final_picture->linesize[i];

                iptr += formatted_picture->linesize[i];

            }

        }

        fill_pad_region((AVPicture*)final_picture, enc->height, enc->width,

                ost->padtop, ost->padbottom, ost->padleft, ost->padright,

                padcolor);

        if (enc->pix_fmt != PIX_FMT_YUV420P) {

            int size;

            av_free(buf);

            /* create temporary picture */

            size = avpicture_get_size(enc->pix_fmt, enc->width, enc->height);

            buf = av_malloc(size);

            if (!buf)

                return;

            final_picture = &picture_format_temp;

            avpicture_fill((AVPicture*)final_picture, buf, enc->pix_fmt, enc->width, enc->height);

            if (img_convert((AVPicture*)final_picture, enc->pix_fmt,

                        (AVPicture*)&ost->pict_tmp, PIX_FMT_YUV420P,

                        enc->width, enc->height) < 0) {

                if (verbose >= 0)

                    fprintf(stderr, "pixel format conversion not handled\n");

                goto the_end;

            }

        }

    } else {

        final_picture = formatted_picture;

    }

    /* duplicates frame if needed */

    /* XXX: pb because no interleaving */

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

        AVPacket pkt;

        av_init_packet(&pkt);

        pkt.stream_index= ost->index;

        if (s->oformat->flags & AVFMT_RAWPICTURE) {

            /* raw pictures are written as AVPicture structure to

               avoid any copies. We support temorarily the older

               method. */

            AVFrame* old_frame = enc->coded_frame;

	    enc->coded_frame = dec->coded_frame; //FIXME/XXX remove this hack

            pkt.data= (uint8_t *)final_picture;

            pkt.size=  sizeof(AVPicture);

            if(dec->coded_frame)

                pkt.pts= dec->coded_frame->pts;

            if(dec->coded_frame && dec->coded_frame->key_frame)

                pkt.flags |= PKT_FLAG_KEY;

            av_write_frame(s, &pkt);

	    enc->coded_frame = old_frame;

        } else {

            AVFrame big_picture;

            big_picture= *final_picture;

            /* better than nothing: use input picture interlaced

               settings */

            big_picture.interlaced_frame = in_picture->interlaced_frame;

            if(do_interlace_me || do_interlace_dct){

                if(top_field_first == -1)

                    big_picture.top_field_first = in_picture->top_field_first;

                else

                    big_picture.top_field_first = 1;

            }

            /* handles sameq here. This is not correct because it may

               not be a global option */

            if (same_quality) {

                big_picture.quality = ist->st->quality;

            }else

                big_picture.quality = ost->st->quality;

            if(!me_threshold)

                big_picture.pict_type = 0;

            big_picture.pts = AV_NOPTS_VALUE; //FIXME

            ret = avcodec_encode_video(enc,

                                       video_buffer, VIDEO_BUFFER_SIZE,

                                       &big_picture);

            //enc->frame_number = enc->real_pict_num;

            if(ret){

                pkt.data= video_buffer;

                pkt.size= ret;

                if(enc->coded_frame)

                    pkt.pts= enc->coded_frame->pts;

                if(enc->coded_frame && enc->coded_frame->key_frame)

                    pkt.flags |= PKT_FLAG_KEY;

                av_write_frame(s, &pkt);

                *frame_size = ret;

                //fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d",

                //        enc->frame_number-1, enc->real_pict_num, ret,

                //        enc->pict_type);

                /* if two pass, output log */

                if (ost->logfile && enc->stats_out) {

                    fprintf(ost->logfile, "%s", enc->stats_out);

                }

            }

        }

        ost->frame_number++;

    }

 the_end:

    av_free(buf);

    av_free(buf1);

}


static void av_always_inline filter_mb_edgecv( uint8_t *pix, int stride, const int16_t bS[4], unsigned int qp, H264Context *h ) {

    const int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8);

    const unsigned int index_a = qp - qp_bd_offset + h->slice_alpha_c0_offset;

    const int alpha = alpha_table[index_a];

    const int beta  = beta_table[qp - qp_bd_offset + h->slice_beta_offset];

    if (alpha ==0 || beta == 0) return;

    if( bS[0] < 4 ) {

        int8_t tc[4];

        tc[0] = tc0_table[index_a][bS[0]]+1;

        tc[1] = tc0_table[index_a][bS[1]]+1;

        tc[2] = tc0_table[index_a][bS[2]]+1;

        tc[3] = tc0_table[index_a][bS[3]]+1;

        h->h264dsp.h264_h_loop_filter_chroma(pix, stride, alpha, beta, tc);

    } else {

        h->h264dsp.h264_h_loop_filter_chroma_intra(pix, stride, alpha, beta);

    }

}