static int doTest(uint8_t *ref[4], int refStride[4], int w, int h, int srcFormat, int dstFormat,

                  int srcW, int srcH, int dstW, int dstH, int flags){

    uint8_t *src[4] = {0};

    uint8_t *dst[4] = {0};

    uint8_t *out[4] = {0};

    int srcStride[4], dstStride[4];

    int i;

    uint64_t ssdY, ssdU, ssdV, ssdA=0;

    struct SwsContext *srcContext = NULL, *dstContext = NULL,

                      *outContext = NULL;

    int res;

    res = 0;

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

        // avoid stride % bpp != 0

        if (srcFormat==PIX_FMT_RGB24 || srcFormat==PIX_FMT_BGR24)

            srcStride[i]= srcW*3;

        else if (srcFormat==PIX_FMT_RGB48BE || srcFormat==PIX_FMT_RGB48LE)

            srcStride[i]= srcW*6;

        else

            srcStride[i]= srcW*4;

        if (dstFormat==PIX_FMT_RGB24 || dstFormat==PIX_FMT_BGR24)

            dstStride[i]= dstW*3;

        else if (dstFormat==PIX_FMT_RGB48BE || dstFormat==PIX_FMT_RGB48LE)

            dstStride[i]= dstW*6;

        else

            dstStride[i]= dstW*4;

        src[i]= (uint8_t*) malloc(srcStride[i]*srcH);

        dst[i]= (uint8_t*) malloc(dstStride[i]*dstH);

        out[i]= (uint8_t*) malloc(refStride[i]*h);

        if (!src[i] || !dst[i] || !out[i]) {

            perror("Malloc");

            res = -1;

            goto end;

        }

    }

    srcContext= sws_getContext(w, h, PIX_FMT_YUVA420P, srcW, srcH, srcFormat, flags, NULL, NULL, NULL);

    if (!srcContext) {

        fprintf(stderr, "Failed to get %s ---> %s\n",

                sws_format_name(PIX_FMT_YUVA420P),

                sws_format_name(srcFormat));

        res = -1;

        goto end;

    }

    dstContext= sws_getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, NULL, NULL, NULL);

    if (!dstContext) {

        fprintf(stderr, "Failed to get %s ---> %s\n",

                sws_format_name(srcFormat),

                sws_format_name(dstFormat));

        res = -1;

        goto end;

    }

    outContext= sws_getContext(dstW, dstH, dstFormat, w, h, PIX_FMT_YUVA420P, flags, NULL, NULL, NULL);

    if (!outContext) {

        fprintf(stderr, "Failed to get %s ---> %s\n",

                sws_format_name(dstFormat),

                sws_format_name(PIX_FMT_YUVA420P));

        res = -1;

        goto end;

    }

//    printf("test %X %X %X -> %X %X %X\n", (int)ref[0], (int)ref[1], (int)ref[2],

//        (int)src[0], (int)src[1], (int)src[2]);

    sws_scale(srcContext, ref, refStride, 0, h   , src, srcStride);

    sws_scale(dstContext, src, srcStride, 0, srcH, dst, dstStride);

    sws_scale(outContext, dst, dstStride, 0, dstH, out, refStride);

    ssdY= getSSD(ref[0], out[0], refStride[0], refStride[0], w, h);

    ssdU= getSSD(ref[1], out[1], refStride[1], refStride[1], (w+1)>>1, (h+1)>>1);

    ssdV= getSSD(ref[2], out[2], refStride[2], refStride[2], (w+1)>>1, (h+1)>>1);

    if (isALPHA(srcFormat) && isALPHA(dstFormat))

        ssdA= getSSD(ref[3], out[3], refStride[3], refStride[3], w, h);

    if (srcFormat == PIX_FMT_GRAY8 || dstFormat==PIX_FMT_GRAY8) ssdU=ssdV=0; //FIXME check that output is really gray

    ssdY/= w*h;

    ssdU/= w*h/4;

    ssdV/= w*h/4;

    ssdA/= w*h;

    printf(" %s %dx%d -> %s %4dx%4d flags=%2d SSD=%5"PRId64",%5"PRId64",%5"PRId64",%5"PRId64"\n",

           sws_format_name(srcFormat), srcW, srcH,

           sws_format_name(dstFormat), dstW, dstH,

           flags, ssdY, ssdU, ssdV, ssdA);

    fflush(stdout);

    end:

    sws_freeContext(srcContext);

    sws_freeContext(dstContext);

    sws_freeContext(outContext);

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

        free(src[i]);

        free(dst[i]);

        free(out[i]);

    }

    return res;

}


static ram_addr_t get_start_block(DumpState *s)

{

    RAMBlock *block;

    if (!s->has_filter) {

        s->block = QTAILQ_FIRST(&ram_list.blocks);

        return 0;

    }

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

        if (block->offset >= s->begin + s->length ||

            block->offset + block->length <= s->begin) {

            /* This block is out of the range */

            continue;

        }

        s->block = block;

        if (s->begin > block->offset) {

            s->start = s->begin - block->offset;

        } else {

            s->start = 0;

        }

        return s->start;

    }

    return -1;

}


static int get_cluster_table(BlockDriverState *bs, uint64_t offset,

                             uint64_t **new_l2_table,

                             int *new_l2_index)

{

    BDRVQcowState *s = bs->opaque;

    unsigned int l1_index, l2_index;

    uint64_t l2_offset;

    uint64_t *l2_table = NULL;

    int ret;

    /* seek the the l2 offset in the l1 table */

    l1_index = offset >> (s->l2_bits + s->cluster_bits);

    if (l1_index >= s->l1_size) {

        ret = qcow2_grow_l1_table(bs, l1_index + 1, false);

        if (ret < 0) {

            return ret;

        }

    }

    l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK;

    /* seek the l2 table of the given l2 offset */

    if (s->l1_table[l1_index] & QCOW_OFLAG_COPIED) {

        /* load the l2 table in memory */

        ret = l2_load(bs, l2_offset, &l2_table);

        if (ret < 0) {

            return ret;

        }

    } else {

        /* First allocate a new L2 table (and do COW if needed) */

        ret = l2_allocate(bs, l1_index, &l2_table);

        if (ret < 0) {

            return ret;

        }

        /* Then decrease the refcount of the old table */

        if (l2_offset) {

            qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));

        }

    }

    /* find the cluster offset for the given disk offset */

    l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);

    *new_l2_table = l2_table;

    *new_l2_index = l2_index;

    return 0;

}


static void gem_write(void *opaque, hwaddr offset, uint64_t val,

        unsigned size)

{

    CadenceGEMState *s = (CadenceGEMState *)opaque;

    uint32_t readonly;

    int i;

    DB_PRINT("offset: 0x%04x write: 0x%08x ", (unsigned)offset, (unsigned)val);

    offset >>= 2;

    /* Squash bits which are read only in write value */

    val &= ~(s->regs_ro[offset]);

    /* Preserve (only) bits which are read only and wtc in register */

    readonly = s->regs[offset] & (s->regs_ro[offset] | s->regs_w1c[offset]);

    /* Copy register write to backing store */

    s->regs[offset] = (val & ~s->regs_w1c[offset]) | readonly;

    /* do w1c */

    s->regs[offset] &= ~(s->regs_w1c[offset] & val);

    /* Handle register write side effects */

    switch (offset) {

    case GEM_NWCTRL:

        if (val & GEM_NWCTRL_RXENA) {

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

                gem_get_rx_desc(s, i);

            }

        }

        if (val & GEM_NWCTRL_TXSTART) {

            gem_transmit(s);

        }

        if (!(val & GEM_NWCTRL_TXENA)) {

            /* Reset to start of Q when transmit disabled. */

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

                s->tx_desc_addr[i] = s->regs[GEM_TXQBASE];

            }

        }

        if (gem_can_receive(qemu_get_queue(s->nic))) {

            qemu_flush_queued_packets(qemu_get_queue(s->nic));

        }

        break;

    case GEM_TXSTATUS:

        gem_update_int_status(s);

        break;

    case GEM_RXQBASE:

        s->rx_desc_addr[0] = val;

        break;

    case GEM_RECEIVE_Q1_PTR ... GEM_RECEIVE_Q15_PTR:

        s->rx_desc_addr[offset - GEM_RECEIVE_Q1_PTR + 1] = val;

        break;

    case GEM_TXQBASE:

        s->tx_desc_addr[0] = val;

        break;

    case GEM_TRANSMIT_Q1_PTR ... GEM_TRANSMIT_Q15_PTR:

        s->tx_desc_addr[offset - GEM_TRANSMIT_Q1_PTR + 1] = val;

        break;

    case GEM_RXSTATUS:

        gem_update_int_status(s);

        break;

    case GEM_IER:

        s->regs[GEM_IMR] &= ~val;

        gem_update_int_status(s);

        break;

    case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE:

        s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val;

        gem_update_int_status(s);

        break;

    case GEM_INT_Q8_ENABLE ... GEM_INT_Q15_ENABLE:

        s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_ENABLE] &= ~val;

        gem_update_int_status(s);

        break;

    case GEM_IDR:

        s->regs[GEM_IMR] |= val;

        gem_update_int_status(s);

        break;

    case GEM_INT_Q1_DISABLE ... GEM_INT_Q7_DISABLE:

        s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_DISABLE] |= val;

        gem_update_int_status(s);

        break;

    case GEM_INT_Q8_DISABLE ... GEM_INT_Q15_DISABLE:

        s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_DISABLE] |= val;

        gem_update_int_status(s);

        break;

    case GEM_SPADDR1LO:

    case GEM_SPADDR2LO:

    case GEM_SPADDR3LO:

    case GEM_SPADDR4LO:

        s->sar_active[(offset - GEM_SPADDR1LO) / 2] = false;

        break;

    case GEM_SPADDR1HI:

    case GEM_SPADDR2HI:

    case GEM_SPADDR3HI:

    case GEM_SPADDR4HI:

        s->sar_active[(offset - GEM_SPADDR1HI) / 2] = true;

        break;

    case GEM_PHYMNTNC:

        if (val & GEM_PHYMNTNC_OP_W) {

            uint32_t phy_addr, reg_num;

            phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;

            if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) {

                reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;

                gem_phy_write(s, reg_num, val);

            }

        }

        break;

    }

    DB_PRINT("newval: 0x%08x\n", s->regs[offset]);

}


void pl050_init(uint32_t base, qemu_irq irq, int is_mouse)

{

    int iomemtype;

    pl050_state *s;

    s = (pl050_state *)qemu_mallocz(sizeof(pl050_state));

    iomemtype = cpu_register_io_memory(0, pl050_readfn,

                                       pl050_writefn, s);

    cpu_register_physical_memory(base, 0x00000fff, iomemtype);

    s->base = base;

    s->irq = irq;

    s->is_mouse = is_mouse;

    if (is_mouse)

        s->dev = ps2_mouse_init(pl050_update, s);

    else

        s->dev = ps2_kbd_init(pl050_update, s);

    /* ??? Save/restore.  */

}


static int matroska_parse_cluster(MatroskaDemuxContext *matroska)

{

    MatroskaCluster cluster = { 0 };

    EbmlList *blocks_list;

    MatroskaBlock *blocks;

    int i, res;

    int64_t pos = url_ftell(matroska->ctx->pb);

    matroska->prev_pkt = NULL;

    if (matroska->has_cluster_id){

        /* For the first cluster we parse, its ID was already read as

           part of matroska_read_header(), so don't read it again */

        res = ebml_parse_id(matroska, matroska_clusters,

                            MATROSKA_ID_CLUSTER, &cluster);

        pos -= 4;  /* sizeof the ID which was already read */

        matroska->has_cluster_id = 0;

    } else

        res = ebml_parse(matroska, matroska_clusters, &cluster);

    blocks_list = &cluster.blocks;

    blocks = blocks_list->elem;

    for (i=0; i<blocks_list->nb_elem; i++)

        if (blocks[i].bin.size > 0) {

            int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1;

            res=matroska_parse_block(matroska,

                                     blocks[i].bin.data, blocks[i].bin.size,

                                     blocks[i].bin.pos,  cluster.timecode,

                                     blocks[i].duration, is_keyframe,

                                     pos);

        }

    ebml_free(matroska_cluster, &cluster);

    if (res < 0)  matroska->done = 1;

    return res;

}


static av_cold void init_mdct_win(TwinContext *tctx)

{

    int i,j;

    const ModeTab *mtab = tctx->mtab;

    int size_s = mtab->size / mtab->fmode[FT_SHORT].sub;

    int size_m = mtab->size / mtab->fmode[FT_MEDIUM].sub;

    int channels = tctx->avctx->channels;

    float norm = channels == 1 ? 2. : 1.;

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

        int bsize = tctx->mtab->size/tctx->mtab->fmode[i].sub;

        ff_mdct_init(&tctx->mdct_ctx[i], av_log2(bsize) + 1, 1,

                     -sqrt(norm/bsize) / (1<<15));

    }

    tctx->tmp_buf  = av_malloc(mtab->size            * sizeof(*tctx->tmp_buf));

    tctx->spectrum  = av_malloc(2*mtab->size*channels*sizeof(float));

    tctx->curr_frame = av_malloc(2*mtab->size*channels*sizeof(float));

    tctx->prev_frame  = av_malloc(2*mtab->size*channels*sizeof(float));

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

        int m = 4*mtab->size/mtab->fmode[i].sub;

        double freq = 2*M_PI/m;

        tctx->cos_tabs[i] = av_malloc((m/4)*sizeof(*tctx->cos_tabs));

        for (j = 0; j <= m/8; j++)

            tctx->cos_tabs[i][j] = cos((2*j + 1)*freq);

        for (j = 1; j <  m/8; j++)

            tctx->cos_tabs[i][m/4-j] = tctx->cos_tabs[i][j];

    }

    ff_init_ff_sine_windows(av_log2(size_m));

    ff_init_ff_sine_windows(av_log2(size_s/2));

    ff_init_ff_sine_windows(av_log2(mtab->size));

}


static MemTxResult memory_region_oldmmio_write_accessor(MemoryRegion *mr,

                                                        hwaddr addr,

                                                        uint64_t *value,

                                                        unsigned size,

                                                        unsigned shift,

                                                        uint64_t mask,

                                                        MemTxAttrs attrs)

{

    uint64_t tmp;

    tmp = (*value >> shift) & mask;

    if (mr->subpage) {

        trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size);

    } else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {

        hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);

        trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, size);

    }

    mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);

    return MEMTX_OK;

}


static av_cold int aacPlus_encode_init(AVCodecContext *avctx)

{

    aacPlusAudioContext *s = avctx->priv_data;

    aacplusEncConfiguration *aacplus_cfg;

    /* number of channels */

    if (avctx->channels < 1 || avctx->channels > 2) {

        av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels);

        return -1;

    }

    s->aacplus_handle = aacplusEncOpen(avctx->sample_rate, avctx->channels,

                                       &s->samples_input, &s->max_output_bytes);

    if(!s->aacplus_handle) {

            av_log(avctx, AV_LOG_ERROR, "can't open encoder\n");

            return -1;

    }

    /* check aacplus version */

    aacplus_cfg = aacplusEncGetCurrentConfiguration(s->aacplus_handle);

    /* put the options in the configuration struct */

    if(avctx->profile != FF_PROFILE_AAC_LOW && avctx->profile != FF_PROFILE_UNKNOWN) {

            av_log(avctx, AV_LOG_ERROR, "invalid AAC profile: %d, only LC supported\n", avctx->profile);

            aacplusEncClose(s->aacplus_handle);

            return -1;

    }

    aacplus_cfg->bitRate = avctx->bit_rate;

    aacplus_cfg->bandWidth = avctx->cutoff;

    aacplus_cfg->outputFormat = !(avctx->flags & CODEC_FLAG_GLOBAL_HEADER);

    aacplus_cfg->inputFormat = avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? AACPLUS_INPUT_FLOAT : AACPLUS_INPUT_16BIT;

    if (!aacplusEncSetConfiguration(s->aacplus_handle, aacplus_cfg)) {

        av_log(avctx, AV_LOG_ERROR, "libaacplus doesn't support this output format!\n");

        return -1;

    }

    avctx->frame_size = s->samples_input / avctx->channels;

    /* Set decoder specific info */

    avctx->extradata_size = 0;

    if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {

        unsigned char *buffer = NULL;

        unsigned long decoder_specific_info_size;

        if (aacplusEncGetDecoderSpecificInfo(s->aacplus_handle, &buffer,

                                           &decoder_specific_info_size) == 1) {

            avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE);

            avctx->extradata_size = decoder_specific_info_size;

            memcpy(avctx->extradata, buffer, avctx->extradata_size);

        }

        free(buffer);

    }

    return 0;

}


static uint64_t get_v(ByteIOContext *bc)

{

    uint64_t val = 0;

    for(; bytes_left(bc) > 0; )

    {

	int tmp = get_byte(bc);

	if (tmp&0x80)

	    val= (val<<7) + tmp - 0x80;

	else

	    return (val<<7) + tmp;

    }

    return -1;

}


static av_cold int libgsm_close(AVCodecContext *avctx) {

    gsm_destroy(avctx->priv_data);

    avctx->priv_data = NULL;

    return 0;

}


static int mov_open_dref(ByteIOContext **pb, char *src, MOVDref *ref)

{

    /* try absolute path */

    if (!url_fopen(pb, ref->path, URL_RDONLY))

        return 0;

    /* try relative path */

    if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {

        char filename[1024];

        char *src_path;

        int i, l;

        /* find a source dir */

        src_path = strrchr(src, '/');

        if (src_path)

            src_path++;

        else

            src_path = src;

        /* find a next level down to target */

        for (i = 0, l = strlen(ref->path) - 1; l >= 0; l--)

            if (ref->path[l] == '/') {

                if (i == ref->nlvl_to - 1)

                    break;

                else

                    i++;

            }

        /* compose filename if next level down to target was found */

        if (i == ref->nlvl_to - 1) {

            memcpy(filename, src, src_path - src);

            filename[src_path - src] = 0;

            for (i = 1; i < ref->nlvl_from; i++)

                av_strlcat(filename, "../", 1024);

            av_strlcat(filename, ref->path + l + 1, 1024);

            if (!url_fopen(pb, filename, URL_RDONLY))

                return 0;

        }

    }

    return AVERROR(ENOENT);

};


FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,

                        hwaddr ctl_addr, hwaddr data_addr)

{

    DeviceState *dev;

    SysBusDevice *d;

    FWCfgState *s;

    dev = qdev_create(NULL, TYPE_FW_CFG);

    qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);

    qdev_prop_set_uint32(dev, "data_iobase", data_port);

    d = SYS_BUS_DEVICE(dev);

    s = FW_CFG(dev);

    assert(!object_resolve_path(FW_CFG_PATH, NULL));

    object_property_add_child(qdev_get_machine(), FW_CFG_NAME, OBJECT(s), NULL);

    qdev_init_nofail(dev);

    if (ctl_addr) {

        sysbus_mmio_map(d, 0, ctl_addr);

    }

    if (data_addr) {

        sysbus_mmio_map(d, 1, data_addr);

    }

    fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4);

    fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);

    fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC));

    fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);

    fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);

    fw_cfg_bootsplash(s);

    fw_cfg_reboot(s);

    s->machine_ready.notify = fw_cfg_machine_ready;

    qemu_add_machine_init_done_notifier(&s->machine_ready);

    return s;

}


void qmp_block_passwd(bool has_device, const char *device,

                      bool has_node_name, const char *node_name,

                      const char *password, Error **errp)

{

    Error *local_err = NULL;

    BlockDriverState *bs;

    int err;

    bs = bdrv_lookup_bs(has_device ? device : NULL,

                        has_node_name ? node_name : NULL,

                        &local_err);

    if (local_err) {

        error_propagate(errp, local_err);

        return;

    }

    err = bdrv_set_key(bs, password);

    if (err == -EINVAL) {

        error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));

        return;

    } else if (err < 0) {

        error_set(errp, QERR_INVALID_PASSWORD);

        return;

    }

}


int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)

{

    int ret;

    switch (avctx->codec_type) {

    case AVMEDIA_TYPE_VIDEO:

        if (!frame->width)

            frame->width               = avctx->width;

        if (!frame->height)

            frame->height              = avctx->height;

        if (frame->format < 0)

            frame->format              = avctx->pix_fmt;

        if (!frame->sample_aspect_ratio.num)

            frame->sample_aspect_ratio = avctx->sample_aspect_ratio;

        if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)

            return ret;

        break;

    case AVMEDIA_TYPE_AUDIO:

        if (!frame->sample_rate)

            frame->sample_rate    = avctx->sample_rate;

        if (frame->format < 0)

            frame->format         = avctx->sample_fmt;

        if (!frame->channel_layout) {

            if (avctx->channel_layout) {

                 if (av_get_channel_layout_nb_channels(avctx->channel_layout) !=

                     avctx->channels) {

                     av_log(avctx, AV_LOG_ERROR, "Inconsistent channel "

                            "configuration.\n");

                     return AVERROR(EINVAL);

                 }

                frame->channel_layout = avctx->channel_layout;

            } else {

                if (avctx->channels > FF_SANE_NB_CHANNELS) {

                    av_log(avctx, AV_LOG_ERROR, "Too many channels: %d.\n",

                           avctx->channels);

                    return AVERROR(ENOSYS);

                }

                frame->channel_layout = av_get_default_channel_layout(avctx->channels);

                if (!frame->channel_layout)

                    frame->channel_layout = (1ULL << avctx->channels) - 1;

            }

        }

        break;

    default: return AVERROR(EINVAL);

    }

    frame->pkt_pts = avctx->pkt ? avctx->pkt->pts : AV_NOPTS_VALUE;

    frame->reordered_opaque = avctx->reordered_opaque;

#if FF_API_GET_BUFFER

    /*

     * Wrap an old get_buffer()-allocated buffer in an bunch of AVBuffers.

     * We wrap each plane in its own AVBuffer. Each of those has a reference to

     * a dummy AVBuffer as its private data, unreffing it on free.

     * When all the planes are freed, the dummy buffer's free callback calls

     * release_buffer().

     */

    if (avctx->get_buffer) {

        CompatReleaseBufPriv *priv = NULL;

        AVBufferRef *dummy_buf = NULL;

        int planes, i, ret;

        if (flags & AV_GET_BUFFER_FLAG_REF)

            frame->reference    = 1;

        ret = avctx->get_buffer(avctx, frame);

        if (ret < 0)

            return ret;

        /* return if the buffers are already set up

         * this would happen e.g. when a custom get_buffer() calls

         * avcodec_default_get_buffer

         */

        if (frame->buf[0])

            return 0;

        priv = av_mallocz(sizeof(*priv));

        if (!priv) {

            ret = AVERROR(ENOMEM);

            goto fail;

        }

        priv->avctx = *avctx;

        priv->frame = *frame;

        dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, priv, 0);

        if (!dummy_buf) {

            ret = AVERROR(ENOMEM);

            goto fail;

        }

#define WRAP_PLANE(ref_out, data, data_size)                            \

do {                                                                    \

    AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf);                  \

    if (!dummy_ref) {                                                   \

        ret = AVERROR(ENOMEM);                                          \

        goto fail;                                                      \

    }                                                                   \

    ref_out = av_buffer_create(data, data_size, compat_release_buffer,  \

                               dummy_ref, 0);                           \

    if (!ref_out) {                                                     \

        av_frame_unref(frame);                                          \

        ret = AVERROR(ENOMEM);                                          \

        goto fail;                                                      \

    }                                                                   \

} while (0)

        if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {

            const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);

            if (!desc) {

                ret = AVERROR(EINVAL);

                goto fail;

            }

            planes = (desc->flags & PIX_FMT_PLANAR) ? desc->nb_components : 1;

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

                int h_shift    = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;

                int plane_size = (frame->width >> h_shift) * frame->linesize[i];

                WRAP_PLANE(frame->buf[i], frame->data[i], plane_size);

            }

        } else {

            int planar = av_sample_fmt_is_planar(frame->format);

            planes = planar ? avctx->channels : 1;

            if (planes > FF_ARRAY_ELEMS(frame->buf)) {

                frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf);

                frame->extended_buf = av_malloc(sizeof(*frame->extended_buf) *

                                                frame->nb_extended_buf);

                if (!frame->extended_buf) {

                    ret = AVERROR(ENOMEM);

                    goto fail;

                }

            }

            for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++)

                WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]);

            for (i = 0; i < planes - FF_ARRAY_ELEMS(frame->buf); i++)

                WRAP_PLANE(frame->extended_buf[i],

                           frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)],

                           frame->linesize[0]);

        }

        av_buffer_unref(&dummy_buf);

        return 0;

fail:

        avctx->release_buffer(avctx, frame);

        av_freep(&priv);

        av_buffer_unref(&dummy_buf);

        return ret;

    }

#endif

    return avctx->get_buffer2(avctx, frame, flags);

}


m_get(Slirp *slirp)

{

	register struct mbuf *m;

	int flags = 0;

	DEBUG_CALL("m_get");

	if (slirp->m_freelist.m_next == &slirp->m_freelist) {

		m = (struct mbuf *)malloc(SLIRP_MSIZE);

		if (m == NULL) goto end_error;

		slirp->mbuf_alloced++;

		if (slirp->mbuf_alloced > MBUF_THRESH)

			flags = M_DOFREE;

		m->slirp = slirp;

	} else {

		m = slirp->m_freelist.m_next;

		remque(m);

	}

	/* Insert it in the used list */

	insque(m,&slirp->m_usedlist);

	m->m_flags = (flags | M_USEDLIST);

	/* Initialise it */

	m->m_size = SLIRP_MSIZE - sizeof(struct m_hdr);

	m->m_data = m->m_dat;

	m->m_len = 0;

        m->m_nextpkt = NULL;

        m->m_prevpkt = NULL;

end_error:

	DEBUG_ARG("m = %lx", (long )m);

	return m;

}


uint_fast16_t float64_to_uint16_round_to_zero(float64 a STATUS_PARAM)

{

    int64_t v;

    uint_fast16_t res;

    v = float64_to_int64_round_to_zero(a STATUS_VAR);

    if (v < 0) {

        res = 0;

        float_raise( float_flag_invalid STATUS_VAR);

    } else if (v > 0xffff) {

        res = 0xffff;

        float_raise( float_flag_invalid STATUS_VAR);

    } else {

        res = v;

    }

    return res;

}


static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) {

    uint_fast16_t cb;

    uint8_t *tmp_vlc_bits;

    uint32_t *tmp_vlc_codes;

    GetBitContext *gb=&vc->gb;

    vc->codebook_count=get_bits(gb,8)+1;

    AV_DEBUG(" Codebooks: %d \n", vc->codebook_count);

    vc->codebooks=(vorbis_codebook *)av_mallocz(vc->codebook_count * sizeof(vorbis_codebook));

    tmp_vlc_bits=(uint8_t *)av_mallocz(V_MAX_VLCS * sizeof(uint8_t));

    tmp_vlc_codes=(uint32_t *)av_mallocz(V_MAX_VLCS * sizeof(uint32_t));

    for(cb=0;cb<vc->codebook_count;++cb) {

        vorbis_codebook *codebook_setup=&vc->codebooks[cb];

        uint_fast8_t ordered;

        uint_fast32_t t, used_entries=0;

        uint_fast32_t entries;

        AV_DEBUG(" %d. Codebook \n", cb);

        if (get_bits(gb, 24)!=0x564342) {

            av_log(vc->avccontext, AV_LOG_ERROR, " %"PRIdFAST16". Codebook setup data corrupt. \n", cb);

            goto error;

        }

        codebook_setup->dimensions=get_bits(gb, 16);

        if (codebook_setup->dimensions>16) {

            av_log(vc->avccontext, AV_LOG_ERROR, " %"PRIdFAST16". Codebook's dimension is too large (%d). \n", cb, codebook_setup->dimensions);

            goto error;

        }

        entries=get_bits(gb, 24);

        if (entries>V_MAX_VLCS) {

            av_log(vc->avccontext, AV_LOG_ERROR, " %"PRIdFAST16". Codebook has too many entries (%"PRIdFAST32"). \n", cb, entries);

            goto error;

        }

        ordered=get_bits1(gb);

        AV_DEBUG(" codebook_dimensions %d, codebook_entries %d \n", codebook_setup->dimensions, entries);

        if (!ordered) {

            uint_fast16_t ce;

            uint_fast8_t flag;

            uint_fast8_t sparse=get_bits1(gb);

            AV_DEBUG(" not ordered \n");

            if (sparse) {

                AV_DEBUG(" sparse \n");

                used_entries=0;

                for(ce=0;ce<entries;++ce) {

                    flag=get_bits1(gb);

                    if (flag) {

                        tmp_vlc_bits[ce]=get_bits(gb, 5)+1;

                        ++used_entries;

                    }

                    else tmp_vlc_bits[ce]=0;

                }

            } else {

                AV_DEBUG(" not sparse \n");

                used_entries=entries;

                for(ce=0;ce<entries;++ce) {

                    tmp_vlc_bits[ce]=get_bits(gb, 5)+1;

                }

            }

        } else {

            uint_fast16_t current_entry=0;

            uint_fast8_t current_length=get_bits(gb, 5)+1;

            AV_DEBUG(" ordered, current length: %d \n", current_length);  //FIXME

            used_entries=entries;

            for(;current_entry<used_entries;++current_length) {

                uint_fast16_t i, number;

                AV_DEBUG(" number bits: %d ", ilog(entries - current_entry));

                number=get_bits(gb, ilog(entries - current_entry));

                AV_DEBUG(" number: %d \n", number);

                for(i=current_entry;i<number+current_entry;++i) {

                    if (i<used_entries) tmp_vlc_bits[i]=current_length;

                }

                current_entry+=number;

            }

            if (current_entry>used_entries) {

                av_log(vc->avccontext, AV_LOG_ERROR, " More codelengths than codes in codebook. \n");

                goto error;

            }

        }

        codebook_setup->lookup_type=get_bits(gb, 4);

        AV_DEBUG(" lookup type: %d : %s \n", codebook_setup->lookup_type, codebook_setup->lookup_type ? "vq" : "no lookup" );

// If the codebook is used for (inverse) VQ, calculate codevectors.

        if (codebook_setup->lookup_type==1) {

            uint_fast16_t i, j, k;

            uint_fast16_t codebook_lookup_values=ff_vorbis_nth_root(entries, codebook_setup->dimensions);

            uint_fast16_t codebook_multiplicands[codebook_lookup_values];

            float codebook_minimum_value=vorbisfloat2float(get_bits_long(gb, 32));

            float codebook_delta_value=vorbisfloat2float(get_bits_long(gb, 32));

            uint_fast8_t codebook_value_bits=get_bits(gb, 4)+1;

            uint_fast8_t codebook_sequence_p=get_bits1(gb);

            AV_DEBUG(" We expect %d numbers for building the codevectors. \n", codebook_lookup_values);

            AV_DEBUG("  delta %f minmum %f \n", codebook_delta_value, codebook_minimum_value);

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

                codebook_multiplicands[i]=get_bits(gb, codebook_value_bits);

                AV_DEBUG(" multiplicands*delta+minmum : %e \n", (float)codebook_multiplicands[i]*codebook_delta_value+codebook_minimum_value);

                AV_DEBUG(" multiplicand %d \n", codebook_multiplicands[i]);

            }

// Weed out unused vlcs and build codevector vector

            codebook_setup->codevectors=(float *)av_mallocz(used_entries*codebook_setup->dimensions * sizeof(float));

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

                uint_fast8_t dim=codebook_setup->dimensions;

                if (tmp_vlc_bits[i]) {

                    float last=0.0;

                    uint_fast32_t lookup_offset=i;

#ifdef V_DEBUG

                    av_log(vc->avccontext, AV_LOG_INFO, "Lookup offset %d ,", i);

#endif

                    for(k=0;k<dim;++k) {

                        uint_fast32_t multiplicand_offset = lookup_offset % codebook_lookup_values;

                        codebook_setup->codevectors[j*dim+k]=codebook_multiplicands[multiplicand_offset]*codebook_delta_value+codebook_minimum_value+last;

                        if (codebook_sequence_p) {

                            last=codebook_setup->codevectors[j*dim+k];

                        }

                        lookup_offset/=codebook_lookup_values;

                    }

                    tmp_vlc_bits[j]=tmp_vlc_bits[i];

#ifdef V_DEBUG

                    av_log(vc->avccontext, AV_LOG_INFO, "real lookup offset %d, vector: ", j);

                    for(k=0;k<dim;++k) {

                        av_log(vc->avccontext, AV_LOG_INFO, " %f ", codebook_setup->codevectors[j*dim+k]);

                    }

                    av_log(vc->avccontext, AV_LOG_INFO, "\n");

#endif

                    ++j;

                }

            }

            if (j!=used_entries) {

                av_log(vc->avccontext, AV_LOG_ERROR, "Bug in codevector vector building code. \n");

                goto error;

            }

            entries=used_entries;

        }

        else if (codebook_setup->lookup_type>=2) {

            av_log(vc->avccontext, AV_LOG_ERROR, "Codebook lookup type not supported. \n");

            goto error;

        }

// Initialize VLC table

        if (ff_vorbis_len2vlc(tmp_vlc_bits, tmp_vlc_codes, entries)) {

            av_log(vc->avccontext, AV_LOG_ERROR, " Invalid code lengths while generating vlcs. \n");

            goto error;

        }

        codebook_setup->maxdepth=0;

        for(t=0;t<entries;++t)

            if (tmp_vlc_bits[t]>=codebook_setup->maxdepth) codebook_setup->maxdepth=tmp_vlc_bits[t];

        if(codebook_setup->maxdepth > 3*V_NB_BITS) codebook_setup->nb_bits=V_NB_BITS2;

        else                                       codebook_setup->nb_bits=V_NB_BITS;

        codebook_setup->maxdepth=(codebook_setup->maxdepth+codebook_setup->nb_bits-1)/codebook_setup->nb_bits;

        if (init_vlc(&codebook_setup->vlc, codebook_setup->nb_bits, entries, tmp_vlc_bits, sizeof(*tmp_vlc_bits), sizeof(*tmp_vlc_bits), tmp_vlc_codes, sizeof(*tmp_vlc_codes), sizeof(*tmp_vlc_codes), INIT_VLC_LE)) {

            av_log(vc->avccontext, AV_LOG_ERROR, " Error generating vlc tables. \n");

            goto error;

        }

    }

    av_free(tmp_vlc_bits);

    av_free(tmp_vlc_codes);

    return 0;

// Error:

error:

    av_free(tmp_vlc_bits);

    av_free(tmp_vlc_codes);

    return 1;

}


static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg)

{

    Picture *pic = NULL;

    int64_t pts;

    int i, display_picture_number = 0, ret;

    int encoding_delay = s->max_b_frames ? s->max_b_frames

                                         : (s->low_delay ? 0 : 1);

    int flush_offset = 1;

    int direct = 1;

    if (pic_arg) {

        pts = pic_arg->pts;

        display_picture_number = s->input_picture_number++;

        if (pts != AV_NOPTS_VALUE) {

            if (s->user_specified_pts != AV_NOPTS_VALUE) {

                int64_t last = s->user_specified_pts;

                if (pts <= last) {

                    av_log(s->avctx, AV_LOG_ERROR,

                           "Invalid pts (%"PRId64") <= last (%"PRId64")\n",

                           pts, last);

                    return AVERROR(EINVAL);

                }

                if (!s->low_delay && display_picture_number == 1)

                    s->dts_delta = pts - last;

            }

            s->user_specified_pts = pts;

        } else {

            if (s->user_specified_pts != AV_NOPTS_VALUE) {

                s->user_specified_pts =

                pts = s->user_specified_pts + 1;

                av_log(s->avctx, AV_LOG_INFO,

                       "Warning: AVFrame.pts=? trying to guess (%"PRId64")\n",

                       pts);

            } else {

                pts = display_picture_number;

            }

        }

        if (!pic_arg->buf[0] ||

            pic_arg->linesize[0] != s->linesize ||

            pic_arg->linesize[1] != s->uvlinesize ||

            pic_arg->linesize[2] != s->uvlinesize)

            direct = 0;

        if ((s->width & 15) || (s->height & 15))

            direct = 0;

        if (((intptr_t)(pic_arg->data[0])) & (STRIDE_ALIGN-1))

            direct = 0;

        if (s->linesize & (STRIDE_ALIGN-1))

            direct = 0;

        ff_dlog(s->avctx, "%d %d %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"\n", pic_arg->linesize[0],

                pic_arg->linesize[1], s->linesize, s->uvlinesize);

        i = ff_find_unused_picture(s->avctx, s->picture, direct);

        if (i < 0)

            return i;

        pic = &s->picture[i];

        pic->reference = 3;

        if (direct) {

            if ((ret = av_frame_ref(pic->f, pic_arg)) < 0)

                return ret;

        }

        ret = alloc_picture(s, pic, direct);

        if (ret < 0)

            return ret;

        if (!direct) {

            if (pic->f->data[0] + INPLACE_OFFSET == pic_arg->data[0] &&

                pic->f->data[1] + INPLACE_OFFSET == pic_arg->data[1] &&

                pic->f->data[2] + INPLACE_OFFSET == pic_arg->data[2]) {

                // empty

            } else {

                int h_chroma_shift, v_chroma_shift;

                av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt,

                                                 &h_chroma_shift,

                                                 &v_chroma_shift);

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

                    int src_stride = pic_arg->linesize[i];

                    int dst_stride = i ? s->uvlinesize : s->linesize;

                    int h_shift = i ? h_chroma_shift : 0;

                    int v_shift = i ? v_chroma_shift : 0;

                    int w = s->width  >> h_shift;

                    int h = s->height >> v_shift;

                    uint8_t *src = pic_arg->data[i];

                    uint8_t *dst = pic->f->data[i];

                    int vpad = 16;

                    if (   s->codec_id == AV_CODEC_ID_MPEG2VIDEO

                        && !s->progressive_sequence

                        && FFALIGN(s->height, 32) - s->height > 16)

                        vpad = 32;

                    if (!s->avctx->rc_buffer_size)

                        dst += INPLACE_OFFSET;

                    if (src_stride == dst_stride)

                        memcpy(dst, src, src_stride * h);

                    else {

                        int h2 = h;

                        uint8_t *dst2 = dst;

                        while (h2--) {

                            memcpy(dst2, src, w);

                            dst2 += dst_stride;

                            src += src_stride;

                        }

                    }

                    if ((s->width & 15) || (s->height & (vpad-1))) {

                        s->mpvencdsp.draw_edges(dst, dst_stride,

                                                w, h,

                                                16 >> h_shift,

                                                vpad >> v_shift,

                                                EDGE_BOTTOM);

                    }

                }

            }

        }

        ret = av_frame_copy_props(pic->f, pic_arg);

        if (ret < 0)

            return ret;

        pic->f->display_picture_number = display_picture_number;

        pic->f->pts = pts; // we set this here to avoid modifying pic_arg

    } else {

        /* Flushing: When we have not received enough input frames,

         * ensure s->input_picture[0] contains the first picture */

        for (flush_offset = 0; flush_offset < encoding_delay + 1; flush_offset++)

            if (s->input_picture[flush_offset])

                break;

        if (flush_offset <= 1)

            flush_offset = 1;

        else

            encoding_delay = encoding_delay - flush_offset + 1;

    }

    /* shift buffer entries */

    for (i = flush_offset; i < MAX_PICTURE_COUNT /*s->encoding_delay + 1*/; i++)

        s->input_picture[i - flush_offset] = s->input_picture[i];

    s->input_picture[encoding_delay] = (Picture*) pic;

    return 0;

}


static int fourxm_read_header(AVFormatContext *s)

{

    AVIOContext *pb = s->pb;

    unsigned int fourcc_tag;

    unsigned int size;

    int header_size;

    FourxmDemuxContext *fourxm = s->priv_data;

    unsigned char *header;

    int i, ret;

    AVStream *st;

    fourxm->track_count = 0;

    fourxm->tracks = NULL;

    fourxm->fps = 1.0;

    /* skip the first 3 32-bit numbers */

    avio_skip(pb, 12);

    /* check for LIST-HEAD */

    GET_LIST_HEADER();

    header_size = size - 4;

    if (fourcc_tag != HEAD_TAG || header_size < 0)

        return AVERROR_INVALIDDATA;

    /* allocate space for the header and load the whole thing */

    header = av_malloc(header_size);

    if (!header)

        return AVERROR(ENOMEM);

    if (avio_read(pb, header, header_size) != header_size){

        av_free(header);

        return AVERROR(EIO);

    /* take the lazy approach and search for any and all vtrk and strk chunks */

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

        fourcc_tag = AV_RL32(&header[i]);

        size = AV_RL32(&header[i + 4]);

        if (size > header_size - i - 8 && (fourcc_tag == vtrk_TAG || fourcc_tag == strk_TAG)) {

            av_log(s, AV_LOG_ERROR, "chunk larger than array %d>%d\n", size, header_size - i - 8);

            return AVERROR_INVALIDDATA;

        if (fourcc_tag == std__TAG) {

            fourxm->fps = av_int2float(AV_RL32(&header[i + 12]));

        } else if (fourcc_tag == vtrk_TAG) {

            /* check that there is enough data */

            if (size != vtrk_SIZE) {

                ret= AVERROR_INVALIDDATA;

            fourxm->width  = AV_RL32(&header[i + 36]);

            fourxm->height = AV_RL32(&header[i + 40]);

            /* allocate a new AVStream */

            st = avformat_new_stream(s, NULL);

            if (!st){

                ret= AVERROR(ENOMEM);

            avpriv_set_pts_info(st, 60, 1, fourxm->fps);

            fourxm->video_stream_index = st->index;

            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;

            st->codec->codec_id = CODEC_ID_4XM;

            st->codec->extradata_size = 4;

            st->codec->extradata = av_malloc(4);

            AV_WL32(st->codec->extradata, AV_RL32(&header[i + 16]));

            st->codec->width  = fourxm->width;

            st->codec->height = fourxm->height;

            i += 8 + size;

        } else if (fourcc_tag == strk_TAG) {

            int current_track;

            /* check that there is enough data */

            if (size != strk_SIZE) {

                ret= AVERROR_INVALIDDATA;

            current_track = AV_RL32(&header[i + 8]);

            if((unsigned)current_track >= UINT_MAX / sizeof(AudioTrack) - 1){

                av_log(s, AV_LOG_ERROR, "current_track too large\n");

            if (current_track + 1 > fourxm->track_count) {

                fourxm->tracks = av_realloc_f(fourxm->tracks,

                                              sizeof(AudioTrack),

                                              current_track + 1);

                if (!fourxm->tracks) {

                    ret = AVERROR(ENOMEM);

                memset(&fourxm->tracks[fourxm->track_count], 0,

                       sizeof(AudioTrack) * (current_track + 1 - fourxm->track_count));

                fourxm->track_count = current_track + 1;

            fourxm->tracks[current_track].adpcm       = AV_RL32(&header[i + 12]);

            fourxm->tracks[current_track].channels    = AV_RL32(&header[i + 36]);

            fourxm->tracks[current_track].sample_rate = AV_RL32(&header[i + 40]);

            fourxm->tracks[current_track].bits        = AV_RL32(&header[i + 44]);

            fourxm->tracks[current_track].audio_pts   = 0;

            if(   fourxm->tracks[current_track].channels    <= 0

               || fourxm->tracks[current_track].sample_rate <= 0

               || fourxm->tracks[current_track].bits        <  0){

                av_log(s, AV_LOG_ERROR, "audio header invalid\n");

            i += 8 + size;

            /* allocate a new AVStream */

            st = avformat_new_stream(s, NULL);

            if (!st){

                ret= AVERROR(ENOMEM);

            st->id = current_track;

            avpriv_set_pts_info(st, 60, 1, fourxm->tracks[current_track].sample_rate);

            fourxm->tracks[current_track].stream_index = st->index;

            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;

            st->codec->codec_tag = 0;

            st->codec->channels              = fourxm->tracks[current_track].channels;

            st->codec->sample_rate           = fourxm->tracks[current_track].sample_rate;

            st->codec->bits_per_coded_sample = fourxm->tracks[current_track].bits;

            st->codec->bit_rate              = st->codec->channels * st->codec->sample_rate *

                st->codec->bits_per_coded_sample;

            st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;

            if (fourxm->tracks[current_track].adpcm){

                st->codec->codec_id = CODEC_ID_ADPCM_4XM;

            }else if (st->codec->bits_per_coded_sample == 8){

                st->codec->codec_id = CODEC_ID_PCM_U8;

            }else

                st->codec->codec_id = CODEC_ID_PCM_S16LE;

    /* skip over the LIST-MOVI chunk (which is where the stream should be */

    GET_LIST_HEADER();

    if (fourcc_tag != MOVI_TAG){

        ret= AVERROR_INVALIDDATA;

    av_free(header);

    /* initialize context members */

    fourxm->video_pts = -1;  /* first frame will push to 0 */

    return 0;

fail:

    av_freep(&fourxm->tracks);

    av_free(header);

    return ret;


static int virtio_ccw_rng_init(VirtioCcwDevice *ccw_dev)

{

    VirtIORNGCcw *dev = VIRTIO_RNG_CCW(ccw_dev);

    DeviceState *vdev = DEVICE(&dev->vdev);

    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));

    if (qdev_init(vdev) < 0) {

        return -1;

    }

    object_property_set_link(OBJECT(dev),

                             OBJECT(dev->vdev.conf.default_backend), "rng",

                             NULL);

    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));

}


static bool cmd_smart(IDEState *s, uint8_t cmd)

{

    int n;

    if (s->hcyl != 0xc2 || s->lcyl != 0x4f) {

        goto abort_cmd;

    }

    if (!s->smart_enabled && s->feature != SMART_ENABLE) {

        goto abort_cmd;

    }

    switch (s->feature) {

    case SMART_DISABLE:

        s->smart_enabled = 0;

        return true;

    case SMART_ENABLE:

        s->smart_enabled = 1;

        return true;

    case SMART_ATTR_AUTOSAVE:

        switch (s->sector) {

        case 0x00:

            s->smart_autosave = 0;

            break;

        case 0xf1:

            s->smart_autosave = 1;

            break;

        default:

            goto abort_cmd;

        }

        return true;

    case SMART_STATUS:

        if (!s->smart_errors) {

            s->hcyl = 0xc2;

            s->lcyl = 0x4f;

        } else {

            s->hcyl = 0x2c;

            s->lcyl = 0xf4;

        }

        return true;

    case SMART_READ_THRESH:

        memset(s->io_buffer, 0, 0x200);

        s->io_buffer[0] = 0x01; /* smart struct version */

        for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {

            s->io_buffer[2 + 0 + (n * 12)] = smart_attributes[n][0];

            s->io_buffer[2 + 1 + (n * 12)] = smart_attributes[n][11];

        }

        /* checksum */

        for (n = 0; n < 511; n++) {

            s->io_buffer[511] += s->io_buffer[n];

        }

        s->io_buffer[511] = 0x100 - s->io_buffer[511];

        s->status = READY_STAT | SEEK_STAT;

        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

        ide_set_irq(s->bus);

        return false;

    case SMART_READ_DATA:

        memset(s->io_buffer, 0, 0x200);

        s->io_buffer[0] = 0x01; /* smart struct version */

        for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {

            int i;

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

                s->io_buffer[2 + i + (n * 12)] = smart_attributes[n][i];

            }

        }

        s->io_buffer[362] = 0x02 | (s->smart_autosave ? 0x80 : 0x00);

        if (s->smart_selftest_count == 0) {

            s->io_buffer[363] = 0;

        } else {

            s->io_buffer[363] =

                s->smart_selftest_data[3 +

                           (s->smart_selftest_count - 1) *

                           24];

        }

        s->io_buffer[364] = 0x20;

        s->io_buffer[365] = 0x01;

        /* offline data collection capacity: execute + self-test*/

        s->io_buffer[367] = (1 << 4 | 1 << 3 | 1);

        s->io_buffer[368] = 0x03; /* smart capability (1) */

        s->io_buffer[369] = 0x00; /* smart capability (2) */

        s->io_buffer[370] = 0x01; /* error logging supported */

        s->io_buffer[372] = 0x02; /* minutes for poll short test */

        s->io_buffer[373] = 0x36; /* minutes for poll ext test */

        s->io_buffer[374] = 0x01; /* minutes for poll conveyance */

        for (n = 0; n < 511; n++) {

            s->io_buffer[511] += s->io_buffer[n];

        }

        s->io_buffer[511] = 0x100 - s->io_buffer[511];

        s->status = READY_STAT | SEEK_STAT;

        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

        ide_set_irq(s->bus);

        return false;

    case SMART_READ_LOG:

        switch (s->sector) {

        case 0x01: /* summary smart error log */

            memset(s->io_buffer, 0, 0x200);

            s->io_buffer[0] = 0x01;

            s->io_buffer[1] = 0x00; /* no error entries */

            s->io_buffer[452] = s->smart_errors & 0xff;

            s->io_buffer[453] = (s->smart_errors & 0xff00) >> 8;

            for (n = 0; n < 511; n++) {

                s->io_buffer[511] += s->io_buffer[n];

            }

            s->io_buffer[511] = 0x100 - s->io_buffer[511];

            break;

        case 0x06: /* smart self test log */

            memset(s->io_buffer, 0, 0x200);

            s->io_buffer[0] = 0x01;

            if (s->smart_selftest_count == 0) {

                s->io_buffer[508] = 0;

            } else {

                s->io_buffer[508] = s->smart_selftest_count;

                for (n = 2; n < 506; n++)  {

                    s->io_buffer[n] = s->smart_selftest_data[n];

                }

            }

            for (n = 0; n < 511; n++) {

                s->io_buffer[511] += s->io_buffer[n];

            }

            s->io_buffer[511] = 0x100 - s->io_buffer[511];

            break;

        default:

            goto abort_cmd;

        }

        s->status = READY_STAT | SEEK_STAT;

        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

        ide_set_irq(s->bus);

        return false;

    case SMART_EXECUTE_OFFLINE:

        switch (s->sector) {

        case 0: /* off-line routine */

        case 1: /* short self test */

        case 2: /* extended self test */

            s->smart_selftest_count++;

            if (s->smart_selftest_count > 21) {

                s->smart_selftest_count = 0;

            }

            n = 2 + (s->smart_selftest_count - 1) * 24;

            s->smart_selftest_data[n] = s->sector;

            s->smart_selftest_data[n + 1] = 0x00; /* OK and finished */

            s->smart_selftest_data[n + 2] = 0x34; /* hour count lsb */

            s->smart_selftest_data[n + 3] = 0x12; /* hour count msb */

            break;

        default:

            goto abort_cmd;

        }

        return true;

    }

abort_cmd:

    ide_abort_command(s);

    return true;

}


static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,

                        const AVFrame *pict, int *got_packet)

{

    TiffEncoderContext *s = avctx->priv_data;

    const AVFrame *const p = pict;

    int i;

    uint8_t *ptr;

    uint8_t *offset;

    uint32_t strips;

    uint32_t *strip_sizes   = NULL;

    uint32_t *strip_offsets = NULL;

    int bytes_per_row;

    uint32_t res[2]    = { 72, 1 };     // image resolution (72/1)

    uint16_t bpp_tab[] = { 8, 8, 8, 8 };

    int ret = 0;

    int is_yuv = 0;

    uint8_t *yuv_line = NULL;

    int shift_h, shift_v;

    int packet_size;

    const AVPixFmtDescriptor *pfd;

    s->avctx = avctx;

    s->width          = avctx->width;

    s->height         = avctx->height;

    s->subsampling[0] = 1;

    s->subsampling[1] = 1;

    switch (avctx->pix_fmt) {

    case AV_PIX_FMT_RGB48LE:

    case AV_PIX_FMT_GRAY16LE:

    case AV_PIX_FMT_RGBA:

    case AV_PIX_FMT_RGB24:

    case AV_PIX_FMT_GRAY8:

    case AV_PIX_FMT_PAL8:

        pfd    = av_pix_fmt_desc_get(avctx->pix_fmt);

        s->bpp = av_get_bits_per_pixel(pfd);

        if (pfd->flags & AV_PIX_FMT_FLAG_PAL)

            s->photometric_interpretation = TIFF_PHOTOMETRIC_PALETTE;

        else if (pfd->flags & AV_PIX_FMT_FLAG_RGB)

            s->photometric_interpretation = TIFF_PHOTOMETRIC_RGB;

        else

            s->photometric_interpretation = TIFF_PHOTOMETRIC_BLACK_IS_ZERO;

        s->bpp_tab_size = pfd->nb_components;

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

            bpp_tab[i] = s->bpp / s->bpp_tab_size;

        break;

    case AV_PIX_FMT_MONOBLACK:

        s->bpp                        = 1;

        s->photometric_interpretation = TIFF_PHOTOMETRIC_BLACK_IS_ZERO;

        s->bpp_tab_size               = 0;

        break;

    case AV_PIX_FMT_MONOWHITE:

        s->bpp                        = 1;

        s->photometric_interpretation = TIFF_PHOTOMETRIC_WHITE_IS_ZERO;

        s->bpp_tab_size               = 0;

        break;

    case AV_PIX_FMT_YUV420P:

    case AV_PIX_FMT_YUV422P:

    case AV_PIX_FMT_YUV444P:

    case AV_PIX_FMT_YUV410P:

    case AV_PIX_FMT_YUV411P:

        av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &shift_h, &shift_v);

        s->photometric_interpretation = TIFF_PHOTOMETRIC_YCBCR;

        s->bpp                        = 8 + (16 >> (shift_h + shift_v));

        s->subsampling[0]             = 1 << shift_h;

        s->subsampling[1]             = 1 << shift_v;

        s->bpp_tab_size               = 3;

        is_yuv                        = 1;

        break;

    default:

        av_log(s->avctx, AV_LOG_ERROR,

               "This colors format is not supported\n");

        return -1;

    }

    if (s->compr == TIFF_DEFLATE       ||

        s->compr == TIFF_ADOBE_DEFLATE ||

        s->compr == TIFF_LZW)

        // best choice for DEFLATE

        s->rps = s->height;

    else

        // suggest size of strip

        s->rps = FFMAX(8192 / (((s->width * s->bpp) >> 3) + 1), 1);

    // round rps up

    s->rps = ((s->rps - 1) / s->subsampling[1] + 1) * s->subsampling[1];

    strips = (s->height - 1) / s->rps + 1;

    packet_size = avctx->height * ((avctx->width * s->bpp + 7) >> 3) * 2 +

                  avctx->height * 4 + FF_MIN_BUFFER_SIZE;

    if (!pkt->data &&

        (ret = av_new_packet(pkt, packet_size)) < 0) {

        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");

        return ret;

    }

    ptr          = pkt->data;

    s->buf_start = pkt->data;

    s->buf       = &ptr;

    s->buf_size  = pkt->size;

    if (check_size(s, 8))

        goto fail;

    // write header

    bytestream_put_le16(&ptr, 0x4949);

    bytestream_put_le16(&ptr, 42);

    offset = ptr;

    bytestream_put_le32(&ptr, 0);

    strip_sizes   = av_mallocz_array(strips, sizeof(*strip_sizes));

    strip_offsets = av_mallocz_array(strips, sizeof(*strip_offsets));

    if (!strip_sizes || !strip_offsets) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }

    bytes_per_row = (((s->width - 1) / s->subsampling[0] + 1) * s->bpp *

                     s->subsampling[0] * s->subsampling[1] + 7) >> 3;

    if (is_yuv) {

        yuv_line = av_malloc(bytes_per_row);

        if (!yuv_line) {

            av_log(s->avctx, AV_LOG_ERROR, "Not enough memory\n");

            ret = AVERROR(ENOMEM);

            goto fail;

        }

    }

#if CONFIG_ZLIB

    if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) {

        uint8_t *zbuf;

        int zlen, zn;

        int j;

        zlen = bytes_per_row * s->rps;

        zbuf = av_malloc(zlen);

        if (!zbuf) {

            ret = AVERROR(ENOMEM);

            goto fail;

        }

        strip_offsets[0] = ptr - pkt->data;

        zn               = 0;

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

            if (is_yuv) {

                pack_yuv(s, p, yuv_line, j);

                memcpy(zbuf + zn, yuv_line, bytes_per_row);

                j += s->subsampling[1] - 1;

            } else

                memcpy(zbuf + j * bytes_per_row,

                       p->data[0] + j * p->linesize[0], bytes_per_row);

            zn += bytes_per_row;

        }

        ret = encode_strip(s, zbuf, ptr, zn, s->compr);

        av_free(zbuf);

        if (ret < 0) {

            av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n");

            goto fail;

        }

        ptr           += ret;

        strip_sizes[0] = ptr - pkt->data - strip_offsets[0];

    } else

#endif

    if (s->compr == TIFF_LZW) {

        s->lzws = av_malloc(ff_lzw_encode_state_size);

        if (!s->lzws) {

            ret = AVERROR(ENOMEM);

            goto fail;

        }

    }

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

        if (strip_sizes[i / s->rps] == 0) {

            if (s->compr == TIFF_LZW) {

                ff_lzw_encode_init(s->lzws, ptr,

                                   s->buf_size - (*s->buf - s->buf_start),

                                   12, FF_LZW_TIFF, put_bits);

            }

            strip_offsets[i / s->rps] = ptr - pkt->data;

        }

        if (is_yuv) {

            pack_yuv(s, p, yuv_line, i);

            ret = encode_strip(s, yuv_line, ptr, bytes_per_row, s->compr);

            i  += s->subsampling[1] - 1;

        } else

            ret = encode_strip(s, p->data[0] + i * p->linesize[0],

                               ptr, bytes_per_row, s->compr);

        if (ret < 0) {

            av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n");

            goto fail;

        }

        strip_sizes[i / s->rps] += ret;

        ptr                     += ret;

        if (s->compr == TIFF_LZW &&

            (i == s->height - 1 || i % s->rps == s->rps - 1)) {

            ret = ff_lzw_encode_flush(s->lzws, flush_put_bits);

            strip_sizes[(i / s->rps)] += ret;

            ptr                       += ret;

        }

    }

    if (s->compr == TIFF_LZW)

        av_free(s->lzws);

    s->num_entries = 0;

    ADD_ENTRY1(s, TIFF_SUBFILE, TIFF_LONG, 0);

    ADD_ENTRY1(s, TIFF_WIDTH,   TIFF_LONG, s->width);

    ADD_ENTRY1(s, TIFF_HEIGHT,  TIFF_LONG, s->height);

    if (s->bpp_tab_size)

        ADD_ENTRY(s, TIFF_BPP, TIFF_SHORT, s->bpp_tab_size, bpp_tab);

    ADD_ENTRY1(s, TIFF_COMPR,       TIFF_SHORT, s->compr);

    ADD_ENTRY1(s, TIFF_PHOTOMETRIC, TIFF_SHORT, s->photometric_interpretation);

    ADD_ENTRY(s,  TIFF_STRIP_OFFS,  TIFF_LONG,  strips, strip_offsets);

    if (s->bpp_tab_size)

        ADD_ENTRY1(s, TIFF_SAMPLES_PER_PIXEL, TIFF_SHORT, s->bpp_tab_size);

    ADD_ENTRY1(s, TIFF_ROWSPERSTRIP, TIFF_LONG,     s->rps);

    ADD_ENTRY(s,  TIFF_STRIP_SIZE,   TIFF_LONG,     strips, strip_sizes);

    ADD_ENTRY(s,  TIFF_XRES,         TIFF_RATIONAL, 1,      res);

    ADD_ENTRY(s,  TIFF_YRES,         TIFF_RATIONAL, 1,      res);

    ADD_ENTRY1(s, TIFF_RES_UNIT,     TIFF_SHORT,    2);

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

        ADD_ENTRY(s, TIFF_SOFTWARE_NAME, TIFF_STRING,

                  strlen(LIBAVCODEC_IDENT) + 1, LIBAVCODEC_IDENT);

    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {

        uint16_t pal[256 * 3];

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

            uint32_t rgb = *(uint32_t *) (p->data[1] + i * 4);

            pal[i]       = ((rgb >> 16) & 0xff) * 257;

            pal[i + 256] = ((rgb >>  8) & 0xff) * 257;

            pal[i + 512] =  (rgb        & 0xff) * 257;

        }

        ADD_ENTRY(s, TIFF_PAL, TIFF_SHORT, 256 * 3, pal);

    }

    if (is_yuv) {

        /** according to CCIR Recommendation 601.1 */

        uint32_t refbw[12] = { 15, 1, 235, 1, 128, 1, 240, 1, 128, 1, 240, 1 };

        ADD_ENTRY(s, TIFF_YCBCR_SUBSAMPLING, TIFF_SHORT,    2, s->subsampling);

        ADD_ENTRY(s, TIFF_REFERENCE_BW,      TIFF_RATIONAL, 6, refbw);

    }

    // write offset to dir

    bytestream_put_le32(&offset, ptr - pkt->data);

    if (check_size(s, 6 + s->num_entries * 12)) {

        ret = AVERROR(EINVAL);

        goto fail;

    }

    bytestream_put_le16(&ptr, s->num_entries);  // write tag count

    bytestream_put_buffer(&ptr, s->entries, s->num_entries * 12);

    bytestream_put_le32(&ptr, 0);

    pkt->size   = ptr - pkt->data;

    pkt->flags |= AV_PKT_FLAG_KEY;

    *got_packet = 1;

fail:

    av_free(strip_sizes);

    av_free(strip_offsets);

    av_free(yuv_line);

    return ret;

}


static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)

{

    DeviceState *dev = DEVICE(pci_dev);

    VMXNET3State *s = VMXNET3(pci_dev);

    VMW_CBPRN("Starting init...");

    memory_region_init_io(&s->bar0, OBJECT(s), &b0_ops, s,

                          "vmxnet3-b0", VMXNET3_PT_REG_SIZE);

    pci_register_bar(pci_dev, VMXNET3_BAR0_IDX,

                     PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);

    memory_region_init_io(&s->bar1, OBJECT(s), &b1_ops, s,

                          "vmxnet3-b1", VMXNET3_VD_REG_SIZE);

    pci_register_bar(pci_dev, VMXNET3_BAR1_IDX,

                     PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);

    memory_region_init(&s->msix_bar, OBJECT(s), "vmxnet3-msix-bar",

                       VMXNET3_MSIX_BAR_SIZE);

    pci_register_bar(pci_dev, VMXNET3_MSIX_BAR_IDX,

                     PCI_BASE_ADDRESS_SPACE_MEMORY, &s->msix_bar);

    vmxnet3_reset_interrupt_states(s);

    /* Interrupt pin A */

    pci_dev->config[PCI_INTERRUPT_PIN] = 0x01;

    if (!vmxnet3_init_msix(s)) {

        VMW_WRPRN("Failed to initialize MSI-X, configuration is inconsistent.");

    }

    if (!vmxnet3_init_msi(s)) {

        VMW_WRPRN("Failed to initialize MSI, configuration is inconsistent.");

    }

    vmxnet3_net_init(s);

    if (pci_is_express(pci_dev)) {

        if (pci_bus_is_express(pci_dev->bus)) {

            pcie_endpoint_cap_init(pci_dev, VMXNET3_EXP_EP_OFFSET);

        }

        pcie_dev_ser_num_init(pci_dev, VMXNET3_DSN_OFFSET,

                              vmxnet3_device_serial_num(s));

    }

    register_savevm(dev, "vmxnet3-msix", -1, 1,

                    vmxnet3_msix_save, vmxnet3_msix_load, s);

}


void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)

{

    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));

    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);

    int r;

    if (vblk->dataplane_started || s->starting) {

        return;

    }

    s->starting = true;

    s->vq = virtio_get_queue(s->vdev, 0);

    /* Set up guest notifier (irq) */

    r = k->set_guest_notifiers(qbus->parent, 1, true);

    if (r != 0) {

        fprintf(stderr, "virtio-blk failed to set guest notifier (%d), "

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

        goto fail_guest_notifiers;

    }

    s->guest_notifier = virtio_queue_get_guest_notifier(s->vq);

    /* Set up virtqueue notify */

    r = k->set_host_notifier(qbus->parent, 0, true);

    if (r != 0) {

        fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r);

        goto fail_host_notifier;

    }

    s->starting = false;

    vblk->dataplane_started = true;

    trace_virtio_blk_data_plane_start(s);

    blk_set_aio_context(s->conf->conf.blk, s->ctx);

    /* Kick right away to begin processing requests already in vring */

    event_notifier_set(virtio_queue_get_host_notifier(s->vq));

    /* Get this show started by hooking up our callbacks */

    aio_context_acquire(s->ctx);

    virtio_queue_aio_set_host_notifier_handler(s->vq, s->ctx, true, true);

    aio_context_release(s->ctx);

    return;

  fail_host_notifier:

    k->set_guest_notifiers(qbus->parent, 1, false);

  fail_guest_notifiers:

    vblk->dataplane_disabled = true;

    s->starting = false;

    vblk->dataplane_started = true;

}


int do_subchannel_work_passthrough(SubchDev *sch)

{

    int ret = 0;

    SCSW *s = &sch->curr_status.scsw;

    if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {

        /* TODO: Clear handling */

        sch_handle_clear_func(sch);

    } else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {

        /* TODO: Halt handling */

        sch_handle_halt_func(sch);

    } else if (s->ctrl & SCSW_FCTL_START_FUNC) {

        ret = sch_handle_start_func_passthrough(sch);

    }

    return ret;

}


static void icp_control_init(uint32_t base)

{

    int iomemtype;

    icp_control_state *s;

    s = (icp_control_state *)qemu_mallocz(sizeof(icp_control_state));

    iomemtype = cpu_register_io_memory(0, icp_control_readfn,

                                       icp_control_writefn, s);

    cpu_register_physical_memory(base, 0x007fffff, iomemtype);

    s->base = base;

    /* ??? Save/restore.  */

}


static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)

{

    NSVContext *nsv = s->priv_data;

    ByteIOContext *pb = &s->pb;

    uint32_t tag, tag1, handler;

    int codec_type, stream_index, frame_period, bit_rate, scale, rate;

    unsigned int file_size, size, nb_frames;

    int64_t duration;

    int strings_size;

    int table_entries;

    int table_entries_used;

    int i, n;

    AVStream *st;

    NSVStream *ast;

    PRINT(("%s()\n", __FUNCTION__));

    nsv->state = NSV_UNSYNC; /* in case we fail */

    size = get_le32(pb);

    if (size < 28)

    nsv->NSVf_end = size;

    //s->file_size = (uint32_t)get_le32(pb);

    file_size = (uint32_t)get_le32(pb);

    PRINT(("NSV NSVf chunk_size %ld\n", size));

    PRINT(("NSV NSVf file_size %Ld\n", file_size));

    duration = get_le32(pb); /* in ms */

    nsv->duration = duration * AV_TIME_BASE / 1000; /* convert */

    PRINT(("NSV NSVf duration %Ld ms\n", duration));

    // XXX: store it in AVStreams

    strings_size = get_le32(pb);

    table_entries = get_le32(pb);

    table_entries_used = get_le32(pb);

    PRINT(("NSV NSVf info-strings size: %d, table entries: %d, bis %d\n",

            strings_size, table_entries, table_entries_used));

    if (url_feof(pb))

    PRINT(("NSV got header; filepos %Ld\n", url_ftell(pb)));

    if (strings_size > 0) {

        char *strings; /* last byte will be '\0' to play safe with str*() */

        char *p, *endp;

        char *token, *value;

        char quote;

        p = strings = av_mallocz(strings_size + 1);

        endp = strings + strings_size;

        get_buffer(pb, strings, strings_size);

        while (p < endp) {

            while (*p == ' ')

                p++; /* strip out spaces */

            if (p >= endp-2)

                break;

            token = p;

            p = strchr(p, '=');

            if (!p || p >= endp-2)

                break;

            *p++ = '\0';

            quote = *p++;

            value = p;

            p = strchr(p, quote);

            if (!p || p >= endp)

                break;

            *p++ = '\0';

            PRINT(("NSV NSVf INFO: %s='%s'\n", token, value));

            if (!strcmp(token, "ASPECT")) {

                /* don't care */

            } else if (!strcmp(token, "CREATOR") || !strcmp(token, "Author")) {

                strncpy(s->author, value, 512-1);

            } else if (!strcmp(token, "Copyright")) {

                strncpy(s->copyright, value, 512-1);

            } else if (!strcmp(token, "TITLE") || !strcmp(token, "Title")) {

                strncpy(s->title, value, 512-1);

            }

        }

        av_free(strings);

    }

    if (url_feof(pb))

    PRINT(("NSV got infos; filepos %Ld\n", url_ftell(pb)));

    if (table_entries_used > 0) {

        nsv->index_entries = table_entries_used;

        nsv->nsvf_index_data = av_malloc(table_entries * sizeof(uint32_t));

        get_buffer(pb, nsv->nsvf_index_data, table_entries * sizeof(uint32_t));

    }

    PRINT(("NSV got index; filepos %Ld\n", url_ftell(pb)));

#ifdef DEBUG_DUMP_INDEX

#define V(v) ((v<0x20 || v > 127)?'.':v)

    /* dump index */

    PRINT(("NSV %d INDEX ENTRIES:\n", table_entries));

    PRINT(("NSV [dataoffset][fileoffset]\n", table_entries));

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

        unsigned char b[8];

        url_fseek(pb, size + nsv->nsvf_index_data[i], SEEK_SET);

        get_buffer(pb, b, 8);

        PRINT(("NSV [0x%08lx][0x%08lx]: %02x %02x %02x %02x %02x %02x %02x %02x"

           "%c%c%c%c%c%c%c%c\n",

           nsv->nsvf_index_data[i], size + nsv->nsvf_index_data[i],

           b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],

           V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) ));

    }

    //url_fseek(pb, size, SEEK_SET); /* go back to end of header */

#undef V

#endif

    url_fseek(pb, nsv->base_offset + size, SEEK_SET); /* required for dumbdriving-271.nsv (2 extra bytes) */

    if (url_feof(pb))

    nsv->state = NSV_HAS_READ_NSVF;

    return 0;

}


SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,

                            uint32_t tag, uint32_t lun, void *hba_private)

{

    SCSIRequest *req;

    SCSIBus *bus = scsi_bus_from_device(d);

    BusState *qbus = BUS(bus);

    req = g_malloc0(reqops->size);

    req->refcount = 1;

    req->bus = bus;

    req->dev = d;

    req->tag = tag;

    req->lun = lun;

    req->hba_private = hba_private;

    req->status = -1;

    req->sense_len = 0;

    req->ops = reqops;

    object_ref(OBJECT(d));

    object_ref(OBJECT(qbus->parent));

    trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);

    return req;

}


static void setup_rt_frame(int sig, struct target_sigaction *ka,

                           target_siginfo_t *info,

                           target_sigset_t *set, CPUM68KState *env)

{

    struct target_rt_sigframe *frame;

    abi_ulong frame_addr;

    abi_ulong retcode_addr;

    abi_ulong info_addr;

    abi_ulong uc_addr;

    int err = 0;

    int i;

    frame_addr = get_sigframe(ka, env, sizeof *frame);

    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))

	goto give_sigsegv;

    __put_user(sig, &frame->sig);

    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info);

    __put_user(info_addr, &frame->pinfo);

    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc);

    __put_user(uc_addr, &frame->puc);

    copy_siginfo_to_user(&frame->info, info);

    /* Create the ucontext */

    __put_user(0, &frame->uc.tuc_flags);

    __put_user(0, &frame->uc.tuc_link);

    __put_user(target_sigaltstack_used.ss_sp,

               &frame->uc.tuc_stack.ss_sp);

    __put_user(sas_ss_flags(env->aregs[7]),

               &frame->uc.tuc_stack.ss_flags);

    __put_user(target_sigaltstack_used.ss_size,

               &frame->uc.tuc_stack.ss_size);

    err |= target_rt_setup_ucontext(&frame->uc, env);

    if (err)

            goto give_sigsegv;

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

        if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))

            goto give_sigsegv;

    }

    /* Set up to return from userspace.  */

    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);

    __put_user(retcode_addr, &frame->pretcode);

    /* moveq #,d0; notb d0; trap #0 */

    __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),

               (long *)(frame->retcode + 0));

    __put_user(0x4e40, (short *)(frame->retcode + 4));

    if (err)

        goto give_sigsegv;

    /* Set up to return from userspace */

    env->aregs[7] = frame_addr;

    env->pc = ka->_sa_handler;

    unlock_user_struct(frame, frame_addr, 1);

    return;

give_sigsegv:

    unlock_user_struct(frame, frame_addr, 1);

    force_sig(TARGET_SIGSEGV);

}


static int flush_packet(AVFormatContext *ctx, int stream_index,
                         int64_t pts, int64_t dts, int64_t scr, int trailer_size)
{
    MpegMuxContext *s = ctx->priv_data;
    StreamInfo *stream = ctx->streams[stream_index]->priv_data;
    uint8_t *buf_ptr;
    int size, payload_size, startcode, id, stuffing_size, i, header_len;
    int packet_size;
    uint8_t buffer[128];
    int zero_trail_bytes = 0;
    int pad_packet_bytes = 0;
    int pes_flags;
    int general_pack = 0;  /*"general" pack without data specific to one stream?*/
    int nb_frames;
    id = stream->id;
    av_dlog(ctx, "packet ID=%2x PTS=%0.3f\n", id, pts / 90000.0);
    buf_ptr = buffer;
    if ((s->packet_number % s->pack_header_freq) == 0 || s->last_scr != scr) {
        /* output pack and systems header if needed */
        size = put_pack_header(ctx, buf_ptr, scr);
        buf_ptr += size;
        s->last_scr= scr;
        if (s->is_vcd) {
            /* there is exactly one system header for each stream in a VCD MPEG,
               One in the very first video packet and one in the very first
               audio packet (see VCD standard p. IV-7 and IV-8).*/
            if (stream->packet_number==0) {
                size = put_system_header(ctx, buf_ptr, id);
                buf_ptr += size;
        } else if (s->is_dvd) {
            if (stream->align_iframe || s->packet_number == 0){
                int PES_bytes_to_fill = s->packet_size - size - 10;
                if (pts != AV_NOPTS_VALUE) {
                    if (dts != pts)
                        PES_bytes_to_fill -= 5 + 5;
                    else
                        PES_bytes_to_fill -= 5;
                if (stream->bytes_to_iframe == 0 || s->packet_number == 0) {
                    size = put_system_header(ctx, buf_ptr, 0);
                    buf_ptr += size;
                    size = buf_ptr - buffer;
                    avio_write(ctx->pb, buffer, size);
                    avio_wb32(ctx->pb, PRIVATE_STREAM_2);
                    avio_wb16(ctx->pb, 0x03d4);         // length
                    avio_w8(ctx->pb, 0x00);           // substream ID, 00=PCI
                    for (i = 0; i < 979; i++)
                        avio_w8(ctx->pb, 0x00);
                    avio_wb32(ctx->pb, PRIVATE_STREAM_2);
                    avio_wb16(ctx->pb, 0x03fa);         // length
                    avio_w8(ctx->pb, 0x01);           // substream ID, 01=DSI
                    for (i = 0; i < 1017; i++)
                        avio_w8(ctx->pb, 0x00);
                    memset(buffer, 0, 128);
                    buf_ptr = buffer;
                    s->packet_number++;
                    stream->align_iframe = 0;
                    scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet
                    size = put_pack_header(ctx, buf_ptr, scr);
                    s->last_scr= scr;
                    buf_ptr += size;
                    /* GOP Start */
                } else if (stream->bytes_to_iframe < PES_bytes_to_fill) {
                    pad_packet_bytes = PES_bytes_to_fill - stream->bytes_to_iframe;
        } else {
            if ((s->packet_number % s->system_header_freq) == 0) {
                size = put_system_header(ctx, buf_ptr, 0);
                buf_ptr += size;
    size = buf_ptr - buffer;
    avio_write(ctx->pb, buffer, size);
    packet_size = s->packet_size - size;
    if (s->is_vcd && (id & 0xe0) == AUDIO_ID)
        /* The VCD standard demands that 20 zero bytes follow
           each audio pack (see standard p. IV-8).*/
        zero_trail_bytes += 20;
    if ((s->is_vcd && stream->packet_number==0)
        || (s->is_svcd && s->packet_number==0)) {
        /* for VCD the first pack of each stream contains only the pack header,
           the system header and lots of padding (see VCD standard p. IV-6).
           In the case of an audio pack, 20 zero bytes are also added at
           the end.*/
        /* For SVCD we fill the very first pack to increase compatibility with
           some DVD players. Not mandated by the standard.*/
        if (s->is_svcd)
            general_pack = 1;    /* the system header refers to both streams and no stream data*/
        pad_packet_bytes = packet_size - zero_trail_bytes;
    packet_size -= pad_packet_bytes + zero_trail_bytes;
    if (packet_size > 0) {
        /* packet header size */
        packet_size -= 6;
        /* packet header */
        if (s->is_mpeg2) {
            header_len = 3;
            if (stream->packet_number==0)
                header_len += 3; /* PES extension */
            header_len += 1; /* obligatory stuffing byte */
        } else {
            header_len = 0;
        if (pts != AV_NOPTS_VALUE) {
            if (dts != pts)
                header_len += 5 + 5;
            else
                header_len += 5;
        } else {
            if (!s->is_mpeg2)
                header_len++;
        payload_size = packet_size - header_len;
        if (id < 0xc0) {
            startcode = PRIVATE_STREAM_1;
            payload_size -= 1;
            if (id >= 0x40) {
                payload_size -= 3;
                if (id >= 0xa0)
                    payload_size -= 3;
        } else {
            startcode = 0x100 + id;
        stuffing_size = payload_size - av_fifo_size(stream->fifo);
        // first byte does not fit -> reset pts/dts + stuffing
        if(payload_size <= trailer_size && pts != AV_NOPTS_VALUE){
            int timestamp_len=0;
            if(dts != pts)
                timestamp_len += 5;
            if(pts != AV_NOPTS_VALUE)
                timestamp_len += s->is_mpeg2 ? 5 : 4;
            pts=dts= AV_NOPTS_VALUE;
            header_len -= timestamp_len;
            if (s->is_dvd && stream->align_iframe) {
                pad_packet_bytes += timestamp_len;
                packet_size  -= timestamp_len;
            } else {
                payload_size += timestamp_len;
            stuffing_size += timestamp_len;
            if(payload_size > trailer_size)
                stuffing_size += payload_size - trailer_size;
        if (pad_packet_bytes > 0 && pad_packet_bytes <= 7) { // can't use padding, so use stuffing
            packet_size += pad_packet_bytes;
            payload_size += pad_packet_bytes; // undo the previous adjustment
            if (stuffing_size < 0) {
                stuffing_size  = pad_packet_bytes;
            } else {
                stuffing_size += pad_packet_bytes;
            pad_packet_bytes = 0;
        if (stuffing_size < 0)
            stuffing_size = 0;
        if (stuffing_size > 16) {    /*<=16 for MPEG-1, <=32 for MPEG-2*/
            pad_packet_bytes += stuffing_size;
            packet_size      -= stuffing_size;
            payload_size     -= stuffing_size;
            stuffing_size = 0;
        nb_frames= get_nb_frames(ctx, stream, payload_size - stuffing_size);
        avio_wb32(ctx->pb, startcode);
        avio_wb16(ctx->pb, packet_size);
        if (!s->is_mpeg2)
            for(i=0;i<stuffing_size;i++)
                avio_w8(ctx->pb, 0xff);
        if (s->is_mpeg2) {
            avio_w8(ctx->pb, 0x80); /* mpeg2 id */
            pes_flags=0;
            if (pts != AV_NOPTS_VALUE) {
                pes_flags |= 0x80;
                if (dts != pts)
                    pes_flags |= 0x40;
            /* Both the MPEG-2 and the SVCD standards demand that the
               P-STD_buffer_size field be included in the first packet of
               every stream. (see SVCD standard p. 26 V.2.3.1 and V.2.3.2
               and MPEG-2 standard 2.7.7) */
            if (stream->packet_number == 0)
                pes_flags |= 0x01;
            avio_w8(ctx->pb, pes_flags); /* flags */
            avio_w8(ctx->pb, header_len - 3 + stuffing_size);
            if (pes_flags & 0x80)  /*write pts*/
                put_timestamp(ctx->pb, (pes_flags & 0x40) ? 0x03 : 0x02, pts);
            if (pes_flags & 0x40)  /*write dts*/
                put_timestamp(ctx->pb, 0x01, dts);
            if (pes_flags & 0x01) {  /*write pes extension*/
                avio_w8(ctx->pb, 0x10); /* flags */
                /* P-STD buffer info */
                if ((id & 0xe0) == AUDIO_ID)
                    avio_wb16(ctx->pb, 0x4000 | stream->max_buffer_size/ 128);
                else
                    avio_wb16(ctx->pb, 0x6000 | stream->max_buffer_size/1024);
        } else {
            if (pts != AV_NOPTS_VALUE) {
                if (dts != pts) {
                    put_timestamp(ctx->pb, 0x03, pts);
                    put_timestamp(ctx->pb, 0x01, dts);
                } else {
                    put_timestamp(ctx->pb, 0x02, pts);
            } else {
                avio_w8(ctx->pb, 0x0f);
        if (s->is_mpeg2) {
            /* special stuffing byte that is always written
               to prevent accidental generation of start codes. */
            avio_w8(ctx->pb, 0xff);
            for(i=0;i<stuffing_size;i++)
                avio_w8(ctx->pb, 0xff);
        if (startcode == PRIVATE_STREAM_1) {
            avio_w8(ctx->pb, id);
            if (id >= 0xa0) {
                /* LPCM (XXX: check nb_frames) */
                avio_w8(ctx->pb, 7);
                avio_wb16(ctx->pb, 4); /* skip 3 header bytes */
                avio_w8(ctx->pb, stream->lpcm_header[0]);
                avio_w8(ctx->pb, stream->lpcm_header[1]);
                avio_w8(ctx->pb, stream->lpcm_header[2]);
            } else if (id >= 0x40) {
                /* AC-3 */
                avio_w8(ctx->pb, nb_frames);
                avio_wb16(ctx->pb, trailer_size+1);
        /* output data */
        assert(payload_size - stuffing_size <= av_fifo_size(stream->fifo));
        av_fifo_generic_read(stream->fifo, ctx->pb, payload_size - stuffing_size, &avio_write);
        stream->bytes_to_iframe -= payload_size - stuffing_size;
    }else{
        payload_size=
        stuffing_size= 0;
    if (pad_packet_bytes > 0)
        put_padding_packet(ctx,ctx->pb, pad_packet_bytes);
    for(i=0;i<zero_trail_bytes;i++)
        avio_w8(ctx->pb, 0x00);
    avio_flush(ctx->pb);
    s->packet_number++;
    /* only increase the stream packet number if this pack actually contains
       something that is specific to this stream! I.e. a dedicated header
       or some data.*/
    if (!general_pack)
        stream->packet_number++;
    return payload_size - stuffing_size;


static int mov_read_replaygain(MOVContext *c, AVIOContext *pb, int size)

{

    int64_t end = avio_tell(pb) + size;

    uint8_t *key = NULL, *val = NULL;

    int i;

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

        uint8_t **p;

        uint32_t len, tag;

        if (end - avio_tell(pb) <= 12)

            break;

        len = avio_rb32(pb);

        tag = avio_rl32(pb);

        avio_skip(pb, 4); // flags

        if (len < 12 || len - 12 > end - avio_tell(pb))

            break;

        len -= 12;

        if (tag == MKTAG('n', 'a', 'm', 'e'))

            p = &key;

        else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {

            avio_skip(pb, 4);

            len -= 4;

            p = &val;

        } else

            break;

        *p = av_malloc(len + 1);

        if (!*p)

            break;

        avio_read(pb, *p, len);

        (*p)[len] = 0;

    }

    if (key && val) {

        av_dict_set(&c->fc->metadata, key, val,

                    AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);

        key = val = NULL;

    }

    avio_seek(pb, end, SEEK_SET);

    av_freep(&key);

    av_freep(&val);

    return 0;

}


type_init(vmgenid_register_types)

GuidInfo *qmp_query_vm_generation_id(Error **errp)

{

    GuidInfo *info;

    VmGenIdState *vms;

    Object *obj = find_vmgenid_dev();

    if (!obj) {

        return NULL;

    }

    vms = VMGENID(obj);

    info = g_malloc0(sizeof(*info));

    info->guid = qemu_uuid_unparse_strdup(&vms->guid);

    return info;

}


int av_file_map(const char *filename, uint8_t **bufptr, size_t *size,

                int log_offset, void *log_ctx)

{

    FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };

    int err, fd = open(filename, O_RDONLY);

    struct stat st;

    av_unused void *ptr;

    off_t off_size;

    char errbuf[128];

    *bufptr = NULL;

    if (fd < 0) {

        err = AVERROR(errno);

        av_strerror(err, errbuf, sizeof(errbuf));

        av_log(&file_log_ctx, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, errbuf);

        return err;

    }

    if (fstat(fd, &st) < 0) {

        err = AVERROR(errno);

        av_strerror(err, errbuf, sizeof(errbuf));

        av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in fstat(): %s\n", errbuf);

        close(fd);

        return err;

    }

    off_size = st.st_size;

    if (off_size > SIZE_MAX) {

        av_log(&file_log_ctx, AV_LOG_ERROR,

               "File size for file '%s' is too big\n", filename);

        close(fd);

        return AVERROR(EINVAL);

    }

    *size = off_size;

#if HAVE_MMAP

    ptr = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);

    if ((int)(ptr) == -1) {

        err = AVERROR(errno);

        av_strerror(err, errbuf, sizeof(errbuf));

        av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf);

        close(fd);

        return err;

    }

    *bufptr = ptr;

#elif HAVE_MAPVIEWOFFILE

    {

        HANDLE mh, fh = (HANDLE)_get_osfhandle(fd);

        mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL);

        if (!mh) {

            av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n");

            close(fd);

            return -1;

        }

        ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size);

        CloseHandle(mh);

        if (!ptr) {

            av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n");

            close(fd);

            return -1;

        }

        *bufptr = ptr;

    }

#else

    *bufptr = av_malloc(*size);

    if (!*bufptr) {

        av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n");

        close(fd);

        return AVERROR(ENOMEM);

    }

    read(fd, *bufptr, *size);

#endif

    close(fd);

    return 0;

}


static void gen_op_iwmmxt_setpsr_nz(void)

{

    TCGv tmp = new_tmp();

    gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);

    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);

}


int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    int ret, i, err;
    AVStream *st;
    for (;;) {
        AVPacketList *pktl = s->internal->raw_packet_buffer;
        if (pktl) {
            *pkt = pktl->pkt;
            st   = s->streams[pkt->stream_index];
            if (s->internal->raw_packet_buffer_remaining_size <= 0)
                if ((err = probe_codec(s, st, NULL)) < 0)
                    return err;
            if (st->request_probe <= 0) {
                s->internal->raw_packet_buffer                 = pktl->next;
                s->internal->raw_packet_buffer_remaining_size += pkt->size;
                av_free(pktl);
                return 0;
        pkt->data = NULL;
        pkt->size = 0;
        av_init_packet(pkt);
        ret = s->iformat->read_packet(s, pkt);
        if (ret < 0) {
            /* Some demuxers return FFERROR_REDO when they consume
               data and discard it (ignored streams, junk, extradata).
               We must re-call the demuxer to get the real packet. */
            if (ret == FFERROR_REDO)
                continue;
            if (!pktl || ret == AVERROR(EAGAIN))
                return ret;
            for (i = 0; i < s->nb_streams; i++) {
                st = s->streams[i];
                if (st->probe_packets || st->request_probe > 0)
                    if ((err = probe_codec(s, st, NULL)) < 0)
                        return err;
                av_assert0(st->request_probe <= 0);
            continue;
        if (!pkt->buf) {
            AVPacket tmp = { 0 };
            ret = av_packet_ref(&tmp, pkt);
            if (ret < 0)
                return ret;
            *pkt = tmp;
        if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) &&
            (pkt->flags & AV_PKT_FLAG_CORRUPT)) {
            av_log(s, AV_LOG_WARNING,
                   "Dropped corrupted packet (stream = %d)\n",
                   pkt->stream_index);
            av_packet_unref(pkt);
            continue;
        if (pkt->stream_index >= (unsigned)s->nb_streams) {
            av_log(s, AV_LOG_ERROR, "Invalid stream index %d\n", pkt->stream_index);
            continue;
        st = s->streams[pkt->stream_index];
        if (update_wrap_reference(s, st, pkt->stream_index, pkt) && st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) {
            // correct first time stamps to negative values
            if (!is_relative(st->first_dts))
                st->first_dts = wrap_timestamp(st, st->first_dts);
            if (!is_relative(st->start_time))
                st->start_time = wrap_timestamp(st, st->start_time);
            if (!is_relative(st->cur_dts))
                st->cur_dts = wrap_timestamp(st, st->cur_dts);
        pkt->dts = wrap_timestamp(st, pkt->dts);
        pkt->pts = wrap_timestamp(st, pkt->pts);
        force_codec_ids(s, st);
        /* TODO: audio: time filter; video: frame reordering (pts != dts) */
        if (s->use_wallclock_as_timestamps)
            pkt->dts = pkt->pts = av_rescale_q(av_gettime(), AV_TIME_BASE_Q, st->time_base);
        if (!pktl && st->request_probe <= 0)
            return ret;
        err = add_to_pktbuf(&s->internal->raw_packet_buffer, pkt,
                            &s->internal->raw_packet_buffer_end, 0);
        if (err)
            return err;
        s->internal->raw_packet_buffer_remaining_size -= pkt->size;
        if ((err = probe_codec(s, st, pkt)) < 0)
            return err;


static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,

                      uint8_t (*layout_map)[3],

                      GetBitContext *gb)

{

    int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc, sampling_index;

    int comment_len;

    int tags;

    skip_bits(gb, 2);  // object_type

    sampling_index = get_bits(gb, 4);

    if (m4ac->sampling_index != sampling_index)

        av_log(avctx, AV_LOG_WARNING, "Sample rate index in program config element does not match the sample rate index configured by the container.\n");

    num_front       = get_bits(gb, 4);

    num_side        = get_bits(gb, 4);

    num_back        = get_bits(gb, 4);

    num_lfe         = get_bits(gb, 2);

    num_assoc_data  = get_bits(gb, 3);

    num_cc          = get_bits(gb, 4);

    if (get_bits1(gb))

        skip_bits(gb, 4); // mono_mixdown_tag

    if (get_bits1(gb))

        skip_bits(gb, 4); // stereo_mixdown_tag

    if (get_bits1(gb))

        skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround

    if (get_bits_left(gb) < 4 * (num_front + num_side + num_back + num_lfe + num_assoc_data + num_cc)) {

        av_log(avctx, AV_LOG_ERROR, overread_err);

        return -1;

    }

    decode_channel_map(layout_map       , AAC_CHANNEL_FRONT, gb, num_front);

    tags = num_front;

    decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE,  gb, num_side);

    tags += num_side;

    decode_channel_map(layout_map + tags, AAC_CHANNEL_BACK,  gb, num_back);

    tags += num_back;

    decode_channel_map(layout_map + tags, AAC_CHANNEL_LFE,   gb, num_lfe);

    tags += num_lfe;

    skip_bits_long(gb, 4 * num_assoc_data);

    decode_channel_map(layout_map + tags, AAC_CHANNEL_CC,    gb, num_cc);

    tags += num_cc;

    align_get_bits(gb);

    /* comment field, first byte is length */

    comment_len = get_bits(gb, 8) * 8;

    if (get_bits_left(gb) < comment_len) {

        av_log(avctx, AV_LOG_ERROR, overread_err);

        return -1;

    }

    skip_bits_long(gb, comment_len);

    return tags;

}