void gic_update(GICState *s)

{

    int best_irq;

    int best_prio;

    int irq;

    int irq_level, fiq_level;

    int cpu;

    int cm;

    for (cpu = 0; cpu < s->num_cpu; cpu++) {

        cm = 1 << cpu;

        s->current_pending[cpu] = 1023;

        if (!(s->ctlr & (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1))

            || !(s->cpu_ctlr[cpu] & (GICC_CTLR_EN_GRP0 | GICC_CTLR_EN_GRP1))) {

            qemu_irq_lower(s->parent_irq[cpu]);

            qemu_irq_lower(s->parent_fiq[cpu]);

            continue;

        }

        best_prio = 0x100;

        best_irq = 1023;

        for (irq = 0; irq < s->num_irq; irq++) {

            if (GIC_TEST_ENABLED(irq, cm) && gic_test_pending(s, irq, cm) &&

                (irq < GIC_INTERNAL || GIC_TARGET(irq) & cm)) {

                if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {

                    best_prio = GIC_GET_PRIORITY(irq, cpu);

                    best_irq = irq;

                }

            }

        }

        if (best_irq != 1023) {

            trace_gic_update_bestirq(cpu, best_irq, best_prio,

                s->priority_mask[cpu], s->running_priority[cpu]);

        }

        irq_level = fiq_level = 0;

        if (best_prio < s->priority_mask[cpu]) {

            s->current_pending[cpu] = best_irq;

            if (best_prio < s->running_priority[cpu]) {

                int group = GIC_TEST_GROUP(best_irq, cm);

                if (extract32(s->ctlr, group, 1) &&

                    extract32(s->cpu_ctlr[cpu], group, 1)) {

                    if (group == 0 && s->cpu_ctlr[cpu] & GICC_CTLR_FIQ_EN) {

                        DPRINTF("Raised pending FIQ %d (cpu %d)\n",

                                best_irq, cpu);

                        fiq_level = 1;

                    } else {

                        DPRINTF("Raised pending IRQ %d (cpu %d)\n",

                                best_irq, cpu);

                        irq_level = 1;

                    }

                }

            }

        }

        qemu_set_irq(s->parent_irq[cpu], irq_level);

        qemu_set_irq(s->parent_fiq[cpu], fiq_level);

    }

}


static void residual_interp(int16_t *buf, int16_t *out, int lag,

                            int gain, int *rseed)

{

    int i;

    if (lag) { /* Voiced */

        int16_t *vector_ptr = buf + PITCH_MAX;

        /* Attenuate */

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

            out[i] = vector_ptr[i - lag] * 3 >> 2;

        av_memcpy_backptr((uint8_t*)(out + lag), lag * sizeof(*out),

                          (FRAME_LEN - lag) * sizeof(*out));

    } else {  /* Unvoiced */

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

            *rseed = *rseed * 521 + 259;

            out[i] = gain * *rseed >> 15;

        }

        memset(buf, 0, (FRAME_LEN + PITCH_MAX) * sizeof(*buf));

    }

}


static int mpeg2_decode_block_non_intra(MpegEncContext *s,

                                        DCTELEM *block,

                                        int n)

{

    int level, i, j, run;

    int code;

    RLTable *rl = &rl_mpeg1;

    const UINT8 *scan_table;

    const UINT16 *matrix;

    int mismatch;

    if (s->alternate_scan)

        scan_table = ff_alternate_vertical_scan;

    else

        scan_table = zigzag_direct;

    mismatch = 1;

    {

        int bit_cnt, v;

        UINT32 bit_buf;

        UINT8 *buf_ptr;

        i = 0;

        if (n < 4)

            matrix = s->non_intra_matrix;

        else

            matrix = s->chroma_non_intra_matrix;

        /* special case for the first coef. no need to add a second vlc table */

        SAVE_BITS(&s->gb);

        SHOW_BITS(&s->gb, v, 2);

        if (v & 2) {

            run = 0;

            level = 1 - ((v & 1) << 1);

            FLUSH_BITS(2);

            RESTORE_BITS(&s->gb);

            goto add_coef;

        }

        RESTORE_BITS(&s->gb);

    }

    /* now quantify & encode AC coefs */

    for(;;) {

        code = get_vlc(&s->gb, &rl->vlc);

        if (code < 0)

            return -1;

        if (code == 112) {

            break;

        } else if (code == 111) {

            /* escape */

            run = get_bits(&s->gb, 6);

            level = get_bits(&s->gb, 12);

            level = (level << 20) >> 20;

        } else {

            run = rl->table_run[code];

            level = rl->table_level[code];

            if (get_bits1(&s->gb))

                level = -level;

        }

        i += run;

        if (i >= 64)

            return -1;

    add_coef:

	j = scan_table[i];

        dprintf("%d: run=%d level=%d\n", n, run, level);

        /* XXX: optimize */

        if (level > 0) {

            level = ((level * 2 + 1) * s->qscale * matrix[j]) >> 5;

        } else {

            level = ((-level * 2 + 1) * s->qscale * matrix[j]) >> 5;

            level = -level;

        }

        /* XXX: is it really necessary to saturate since the encoder

           knows whats going on ? */

        mismatch ^= level;

        block[j] = level;

        i++;

    }

    block[63] ^= (mismatch & 1);

    s->block_last_index[n] = i;

    return 0;

}


static int aiff_write_trailer(AVFormatContext *s)

{

    AVIOContext *pb = s->pb;

    AIFFOutputContext *aiff = s->priv_data;

    AVCodecParameters *par = s->streams[0]->codecpar;

    /* Chunks sizes must be even */

    int64_t file_size, end_size;

    end_size = file_size = avio_tell(pb);

    if (file_size & 1) {

        avio_w8(pb, 0);

        end_size++;

    }

    if (s->pb->seekable) {

        /* File length */

        avio_seek(pb, aiff->form, SEEK_SET);

        avio_wb32(pb, file_size - aiff->form - 4);

        /* Number of sample frames */

        avio_seek(pb, aiff->frames, SEEK_SET);

        avio_wb32(pb, (file_size - aiff->ssnd - 12) / par->block_align);

        /* Sound Data chunk size */

        avio_seek(pb, aiff->ssnd, SEEK_SET);

        avio_wb32(pb, file_size - aiff->ssnd - 4);

        /* return to the end */

        avio_seek(pb, end_size, SEEK_SET);

        avio_flush(pb);

    }

    return 0;

}


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

                                 const uint16_t *buf1, const uint16_t *ubuf0,

                                 const uint16_t *ubuf1, const uint16_t *vbuf0,

                                 const uint16_t *vbuf1, const uint16_t *abuf0,

                                 const uint16_t *abuf1, uint8_t *dest,

                                 int dstW, int yalpha, int uvalpha, int y)

{

    //Note 8280 == DSTW_OFFSET but the preprocessor can't handle that there :(

    __asm__ volatile(

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

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

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

        YSCALEYUV2RGB(%%REGBP, %5)

        "pxor    %%mm7, %%mm7                   \n\t"

        /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */

#ifdef DITHER1XBPP

        "paddusb "BLUE_DITHER"(%5), %%mm2      \n\t"

        "paddusb "GREEN_DITHER"(%5), %%mm4      \n\t"

        "paddusb "RED_DITHER"(%5), %%mm5      \n\t"

#endif

        WRITERGB16(%%REGb, 8280(%5), %%REGBP)

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

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

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

           "a" (&c->redDither)

    );

}


struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,

                                         int start, int w, int g, float ener0,

                                         float ener1, float ener01,

                                         int use_pcoeffs, int phase)

{

    int i, w2;

    SingleChannelElement *sce0 = &cpe->ch[0];

    SingleChannelElement *sce1 = &cpe->ch[1];

    float *L = use_pcoeffs ? sce0->pcoeffs : sce0->coeffs;

    float *R = use_pcoeffs ? sce1->pcoeffs : sce1->coeffs;

    float *L34 = &s->scoefs[256*0], *R34 = &s->scoefs[256*1];

    float *IS  = &s->scoefs[256*2], *I34 = &s->scoefs[256*3];

    float dist1 = 0.0f, dist2 = 0.0f;

    struct AACISError is_error = {0};

    if (ener01 <= 0 || ener0 <= 0) {

        is_error.pass = 0;

        return is_error;

    }

    for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {

        FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];

        FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];

        int is_band_type, is_sf_idx = FFMAX(1, sce0->sf_idx[(w+w2)*16+g]-4);

        float e01_34 = phase*pow(ener1/ener0, 3.0/4.0);

        float maxval, dist_spec_err = 0.0f;

        float minthr = FFMIN(band0->threshold, band1->threshold);

        for (i = 0; i < sce0->ics.swb_sizes[g]; i++)

            IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01);

        abs_pow34_v(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]);

        abs_pow34_v(R34, &R[start+(w+w2)*128], sce0->ics.swb_sizes[g]);

        abs_pow34_v(I34, IS,                   sce0->ics.swb_sizes[g]);

        maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34);

        is_band_type = find_min_book(maxval, is_sf_idx);

        dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34,

                                    sce0->ics.swb_sizes[g],

                                    sce0->sf_idx[(w+w2)*16+g],

                                    sce0->band_type[(w+w2)*16+g],

                                    s->lambda / band0->threshold, INFINITY, NULL, NULL, 0);

        dist1 += quantize_band_cost(s, &R[start + (w+w2)*128], R34,

                                    sce1->ics.swb_sizes[g],

                                    sce1->sf_idx[(w+w2)*16+g],

                                    sce1->band_type[(w+w2)*16+g],

                                    s->lambda / band1->threshold, INFINITY, NULL, NULL, 0);

        dist2 += quantize_band_cost(s, IS, I34, sce0->ics.swb_sizes[g],

                                    is_sf_idx, is_band_type,

                                    s->lambda / minthr, INFINITY, NULL, NULL, 0);

        for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {

            dist_spec_err += (L34[i] - I34[i])*(L34[i] - I34[i]);

            dist_spec_err += (R34[i] - I34[i]*e01_34)*(R34[i] - I34[i]*e01_34);

        }

        dist_spec_err *= s->lambda / minthr;

        dist2 += dist_spec_err;

    }

    is_error.pass = dist2 <= dist1;

    is_error.phase = phase;

    is_error.error = fabsf(dist1 - dist2);

    is_error.dist1 = dist1;

    is_error.dist2 = dist2;

    is_error.ener01 = ener01;

    return is_error;

}


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

{

    HLSContext *hls = s->priv_data;

    AVFormatContext *oc = NULL;

    AVStream *st = s->streams[pkt->stream_index];

    int64_t end_pts = hls->recording_time * hls->number;

    int is_ref_pkt = 1;

    int ret, can_split = 1;

    int stream_index = 0;

    if (hls->sequence - hls->nb_entries > hls->start_sequence && hls->init_time > 0) {

        /* reset end_pts, hls->recording_time at end of the init hls list */

        int init_list_dur = hls->init_time * hls->nb_entries * AV_TIME_BASE;

        int after_init_list_dur = (hls->sequence - hls->nb_entries ) * hls->time * AV_TIME_BASE;

        hls->recording_time = hls->time * AV_TIME_BASE;

        end_pts = init_list_dur + after_init_list_dur ;

    }

    if( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ) {

        oc = hls->vtt_avf;

        stream_index = 0;

    } else {

        oc = hls->avf;

        stream_index = pkt->stream_index;

    }

    if (hls->start_pts == AV_NOPTS_VALUE) {

        hls->start_pts = pkt->pts;

        hls->end_pts   = pkt->pts;

    }

    if (hls->has_video) {

        can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&

                    ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));

        is_ref_pkt = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;

    }

    if (pkt->pts == AV_NOPTS_VALUE)

        is_ref_pkt = can_split = 0;

    if (is_ref_pkt) {

        if (hls->new_start) {

            hls->new_start = 0;

            hls->duration = (double)(pkt->pts - hls->end_pts)

                                       * st->time_base.num / st->time_base.den;

            hls->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;

        } else {

            hls->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;

        }

    }

    if (can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base,

                                   end_pts, AV_TIME_BASE_Q) >= 0) {

        int64_t new_start_pos;

        char *old_filename = av_strdup(hls->avf->filename);

        if (!old_filename) {

            return AVERROR(ENOMEM);

        }

        av_write_frame(oc, NULL); /* Flush any buffered data */

        new_start_pos = avio_tell(hls->avf->pb);

        hls->size = new_start_pos - hls->start_pos;

        ff_format_io_close(s, &oc->pb);

        if (hls->vtt_avf) {

            ff_format_io_close(s, &hls->vtt_avf->pb);

        }

        if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {

            if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0))

                if (hls->avf->oformat->priv_class && hls->avf->priv_data)

                    av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0);

            hls_rename_temp_file(s, oc);

        }

        ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);

        hls->start_pos = new_start_pos;

        if (ret < 0) {

            av_free(old_filename);

            return ret;

        }

        hls->end_pts = pkt->pts;

        hls->duration = 0;

        if (hls->flags & HLS_SINGLE_FILE) {

            hls->number++;

        } else if (hls->max_seg_size > 0) {

            if (hls->start_pos >= hls->max_seg_size) {

                hls->sequence++;

                sls_flag_file_rename(hls, old_filename);

                ret = hls_start(s);

                hls->start_pos = 0;

                /* When split segment by byte, the duration is short than hls_time,

                 * so it is not enough one segment duration as hls_time, */

                hls->number--;

            }

            hls->number++;

        } else {

            sls_flag_file_rename(hls, old_filename);

            ret = hls_start(s);

        }

        if (ret < 0) {

            av_free(old_filename);

            return ret;

        }

        if ((ret = hls_window(s, 0)) < 0) {

            av_free(old_filename);

            return ret;

        }

    }

    ret = ff_write_chained(oc, stream_index, pkt, s, 0);

    return ret;

}


static void copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell)

{

    int     h, w, mv_x, mv_y, offset, offset_dst;

    uint8_t *src, *dst;

    /* setup output and reference pointers */

    offset_dst  = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2);

    dst         = plane->pixels[ctx->buf_sel] + offset_dst;

    mv_y        = cell->mv_ptr[0];

    mv_x        = cell->mv_ptr[1];

    offset      = offset_dst + mv_y * plane->pitch + mv_x;

    src         = plane->pixels[ctx->buf_sel ^ 1] + offset;

    h = cell->height << 2;

    for (w = cell->width; w > 0;) {

        /* copy using 16xH blocks */

        if (!((cell->xpos << 2) & 15) && w >= 4) {

            for (; w >= 4; src += 16, dst += 16, w -= 4)

                ctx->dsp.put_no_rnd_pixels_tab[0][0](dst, src, plane->pitch, h);

        }

        /* copy using 8xH blocks */

        if (!((cell->xpos << 2) & 7) && w >= 2) {

            ctx->dsp.put_no_rnd_pixels_tab[1][0](dst, src, plane->pitch, h);

            w -= 2;

            src += 8;

            dst += 8;

        }

        if (w >= 1) {

            copy_block4(dst, src, plane->pitch, plane->pitch, h);

            w--;

            src += 4;

            dst += 4;

        }

    }

}


static void h264_h_loop_filter_chroma_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)

{

    h264_loop_filter_chroma_c(pix, 1, stride, alpha, beta, tc0);

}


static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss,

                              bool last_stage,

                              ram_addr_t dirty_ram_abs)

{

    int tmppages, pages = 0;

    size_t pagesize = qemu_ram_pagesize(pss->block);

    do {

        tmppages = ram_save_target_page(rs, pss, last_stage, dirty_ram_abs);

        if (tmppages < 0) {

            return tmppages;

        }

        pages += tmppages;

        pss->offset += TARGET_PAGE_SIZE;

        dirty_ram_abs += TARGET_PAGE_SIZE;

    } while (pss->offset & (pagesize - 1));

    /* The offset we leave with is the last one we looked at */

    pss->offset -= TARGET_PAGE_SIZE;

    return pages;

}


static void gen_check_privilege(DisasContext *dc)

{

    if (dc->cring) {

        gen_exception_cause(dc, PRIVILEGED_CAUSE);

        dc->is_jmp = DISAS_UPDATE;

    }

}


MigrationState *unix_start_outgoing_migration(Monitor *mon,

                                              const char *path,

					      int64_t bandwidth_limit,

					      int detach,

					      int blk,

					      int inc)

{

    FdMigrationState *s;

    struct sockaddr_un addr;

    int ret;

    addr.sun_family = AF_UNIX;

    snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);

    s = qemu_mallocz(sizeof(*s));

    s->get_error = unix_errno;

    s->write = unix_write;

    s->close = unix_close;

    s->mig_state.cancel = migrate_fd_cancel;

    s->mig_state.get_status = migrate_fd_get_status;

    s->mig_state.release = migrate_fd_release;

    s->mig_state.blk = blk;

    s->mig_state.shared = inc;

    s->state = MIG_STATE_ACTIVE;

    s->mon = NULL;

    s->bandwidth_limit = bandwidth_limit;

    s->fd = socket(PF_UNIX, SOCK_STREAM, 0);

    if (s->fd < 0) {

        dprintf("Unable to open socket");

        goto err_after_alloc;

    }

    socket_set_nonblock(s->fd);

    if (!detach) {

        migrate_fd_monitor_suspend(s, mon);

    }

    do {

        ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));

        if (ret == -1)

	    ret = -(s->get_error(s));

        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)

	    qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s);

    } while (ret == -EINTR);

    if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {

        dprintf("connect failed\n");

        goto err_after_open;

    } else if (ret >= 0)

        migrate_fd_connect(s);

    return &s->mig_state;

err_after_open:

    close(s->fd);

err_after_alloc:

    qemu_free(s);

    return NULL;

}


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

                                int *got_frame_ptr, AVPacket *avpkt)

{

    FDKAACDecContext *s = avctx->priv_data;

    AVFrame *frame = data;

    int ret;

    AAC_DECODER_ERROR err;

    UINT valid = avpkt->size;

    err = aacDecoder_Fill(s->handle, &avpkt->data, &avpkt->size, &valid);

    if (err != AAC_DEC_OK) {

        av_log(avctx, AV_LOG_ERROR, "aacDecoder_Fill() failed: %x\n", err);

        return AVERROR_INVALIDDATA;

    }

    err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, s->decoder_buffer_size, 0);

    if (err == AAC_DEC_NOT_ENOUGH_BITS) {

        ret = avpkt->size - valid;

        goto end;

    }

    if (err != AAC_DEC_OK) {

        av_log(avctx, AV_LOG_ERROR,

               "aacDecoder_DecodeFrame() failed: %x\n", err);

        ret = AVERROR_UNKNOWN;

        goto end;

    }

    if ((ret = get_stream_info(avctx)) < 0)

        goto end;

    frame->nb_samples = avctx->frame_size;

    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)

        goto end;

    memcpy(frame->extended_data[0], s->decoder_buffer,

           avctx->channels * avctx->frame_size *

           av_get_bytes_per_sample(avctx->sample_fmt));

    *got_frame_ptr = 1;

    ret = avpkt->size - valid;

end:

    return ret;

}


static void readline_completion(ReadLineState *rs)

{

    Monitor *mon = cur_mon;

    int len, i, j, max_width, nb_cols, max_prefix;

    char *cmdline;

    rs->nb_completions = 0;

    cmdline = g_malloc(rs->cmd_buf_index + 1);

    memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index);

    cmdline[rs->cmd_buf_index] = '\0';

    rs->completion_finder(cmdline);

    g_free(cmdline);

    /* no completion found */

    if (rs->nb_completions <= 0)

        return;

    if (rs->nb_completions == 1) {

        len = strlen(rs->completions[0]);

        for(i = rs->completion_index; i < len; i++) {

            readline_insert_char(rs, rs->completions[0][i]);

        /* extra space for next argument. XXX: make it more generic */

        if (len > 0 && rs->completions[0][len - 1] != '/')

            readline_insert_char(rs, ' ');

    } else {

        monitor_printf(mon, "\n");

        max_width = 0;

        max_prefix = 0;

        for(i = 0; i < rs->nb_completions; i++) {

            len = strlen(rs->completions[i]);

            if (i==0) {

                max_prefix = len;

            } else {

                if (len < max_prefix)

                    max_prefix = len;

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

                    if (rs->completions[i][j] != rs->completions[0][j])

                        max_prefix = j;

            if (len > max_width)

                max_width = len;

        if (max_prefix > 0)

            for(i = rs->completion_index; i < max_prefix; i++) {

                readline_insert_char(rs, rs->completions[0][i]);

        max_width += 2;

        if (max_width < 10)

            max_width = 10;

        else if (max_width > 80)

            max_width = 80;

        nb_cols = 80 / max_width;

        j = 0;

        for(i = 0; i < rs->nb_completions; i++) {

            monitor_printf(rs->mon, "%-*s", max_width, rs->completions[i]);

            if (++j == nb_cols || i == (rs->nb_completions - 1)) {

                monitor_printf(rs->mon, "\n");

                j = 0;

        readline_show_prompt(rs);


static av_cold int png_dec_init(AVCodecContext *avctx)

{

    PNGDecContext *s = avctx->priv_data;

    s->avctx = avctx;

    s->previous_picture.f = av_frame_alloc();

    s->last_picture.f = av_frame_alloc();

    s->picture.f = av_frame_alloc();

    if (!s->previous_picture.f || !s->last_picture.f || !s->picture.f)

        return AVERROR(ENOMEM);

    if (!avctx->internal->is_copy) {

        avctx->internal->allocate_progress = 1;

        ff_pngdsp_init(&s->dsp);

    }

    return 0;

}


static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride,

                           const uint8_t *src, int size, int width, int lines)

{

    int i, ret = 0;

    int line;

    uint8_t *src2 = av_malloc((unsigned)size +

                              AV_INPUT_BUFFER_PADDING_SIZE);

    if (!src2) {

        av_log(s->avctx, AV_LOG_ERROR,

               "Error allocating temporary buffer\n");

        return AVERROR(ENOMEM);

    }

    if (!s->fill_order) {

        memcpy(src2, src, size);

    } else {

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

            src2[i] = ff_reverse[src[i]];

    }

    memset(src2 + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);

    ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride,

                          s->compr, s->fax_opts);

    if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8)

        for (line = 0; line < lines; line++) {

            horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0);

            dst += stride;

        }

    av_free(src2);

    return ret;

}


int tlb_set_page_exec(CPUState *env, target_ulong vaddr,

                      target_phys_addr_t paddr, int prot,

                      int is_user, int is_softmmu)

{

    PhysPageDesc *p;

    unsigned long pd;

    unsigned int index;

    target_ulong address;

    target_phys_addr_t addend;

    int ret;

    CPUTLBEntry *te;

    p = phys_page_find(paddr >> TARGET_PAGE_BITS);

    if (!p) {

        pd = IO_MEM_UNASSIGNED;

    } else {

        pd = p->phys_offset;

    }

#if defined(DEBUG_TLB)

    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",

           vaddr, (int)paddr, prot, is_user, is_softmmu, pd);

#endif

    ret = 0;

#if !defined(CONFIG_SOFTMMU)

    if (is_softmmu)

#endif

    {

        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {

            /* IO memory case */

            address = vaddr | pd;

            addend = paddr;

        } else {

            /* standard memory */

            address = vaddr;

            addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);

        }

        /* Make accesses to pages with watchpoints go via the

           watchpoint trap routines.  */

        for (i = 0; i < env->nb_watchpoints; i++) {

            if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {

                if (address & ~TARGET_PAGE_MASK) {

                    env->watchpoint[i].is_ram = 0;

                    address = vaddr | io_mem_watch;

                } else {

                    env->watchpoint[i].is_ram = 1;

                    /* TODO: Figure out how to make read watchpoints coexist

                       with code.  */

                    pd = (pd & TARGET_PAGE_MASK) | io_mem_watch | IO_MEM_ROMD;

                }

            }

        }

        index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);

        addend -= vaddr;

        te = &env->tlb_table[is_user][index];

        te->addend = addend;

        if (prot & PAGE_READ) {

            te->addr_read = address;

        } else {

            te->addr_read = -1;

        }

        if (prot & PAGE_EXEC) {

            te->addr_code = address;

        } else {

            te->addr_code = -1;

        }

        if (prot & PAGE_WRITE) {

            if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||

                (pd & IO_MEM_ROMD)) {

                /* write access calls the I/O callback */

                te->addr_write = vaddr |

                    (pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));

            } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&

                       !cpu_physical_memory_is_dirty(pd)) {

                te->addr_write = vaddr | IO_MEM_NOTDIRTY;

            } else {

                te->addr_write = address;

            }

        } else {

            te->addr_write = -1;

        }

    }

#if !defined(CONFIG_SOFTMMU)

    else {

        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {

            /* IO access: no mapping is done as it will be handled by the

               soft MMU */

            if (!(env->hflags & HF_SOFTMMU_MASK))

                ret = 2;

        } else {

            void *map_addr;

            if (vaddr >= MMAP_AREA_END) {

                ret = 2;

            } else {

                if (prot & PROT_WRITE) {

                    if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||

#if defined(TARGET_HAS_SMC) || 1

                        first_tb ||

#endif

                        ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&

                         !cpu_physical_memory_is_dirty(pd))) {

                        /* ROM: we do as if code was inside */

                        /* if code is present, we only map as read only and save the

                           original mapping */

                        VirtPageDesc *vp;

                        vp = virt_page_find_alloc(vaddr >> TARGET_PAGE_BITS, 1);

                        vp->phys_addr = pd;

                        vp->prot = prot;

                        vp->valid_tag = virt_valid_tag;

                        prot &= ~PAGE_WRITE;

                    }

                }

                map_addr = mmap((void *)vaddr, TARGET_PAGE_SIZE, prot,

                                MAP_SHARED | MAP_FIXED, phys_ram_fd, (pd & TARGET_PAGE_MASK));

                if (map_addr == MAP_FAILED) {

                    cpu_abort(env, "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",

                              paddr, vaddr);

                }

            }

        }

    }

#endif

    return ret;

}


static void do_video_out(AVFormatContext *s,

                         AVOutputStream *ost,

                         AVInputStream *ist,

                         AVPicture *in_picture,

                         int *frame_size, AVOutputStream *audio_sync)

{

    int nb_frames, i, ret;

    AVPicture *final_picture, *formatted_picture;

    AVPicture picture_format_temp, picture_crop_temp;

    static uint8_t *video_buffer;

    uint8_t *buf = NULL, *buf1 = NULL;

    AVCodecContext *enc, *dec;

#define VIDEO_BUFFER_SIZE (1024*1024)

    enc = &ost->st->codec;

    dec = &ist->st->codec;

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

    nb_frames = 1;

    *frame_size = 0;

    /* NOTE: the A/V sync is always done by considering the audio is

       the master clock. It is suffisant for transcoding or playing,

       but not for the general case */

    if (audio_sync) {

        /* compute the A-V delay and duplicate/remove frames if needed */

        double adelta, vdelta, av_delay;

        adelta = audio_sync->sync_ipts - ((double)audio_sync->sync_opts *

            s->pts_num / s->pts_den);

        vdelta = ost->sync_ipts - ((double)ost->sync_opts *

            s->pts_num / s->pts_den);

        av_delay = adelta - vdelta;

        //            printf("delay=%f\n", av_delay);

        if (av_delay < -AV_DELAY_MAX)

            nb_frames = 2;

        else if (av_delay > AV_DELAY_MAX)

            nb_frames = 0;

    } else {

        double vdelta;

        vdelta = (double)(ost->st->pts.val) * s->pts_num / s->pts_den - (ost->sync_ipts - ost->sync_ipts_offset);

        if (vdelta < 100 && vdelta > -100 && ost->sync_ipts_offset) {

            if (vdelta < -AV_DELAY_MAX)

                nb_frames = 2;

            else if (vdelta > AV_DELAY_MAX)

                nb_frames = 0;

        } else {

            ost->sync_ipts_offset -= vdelta;

            if (!ost->sync_ipts_offset)

                ost->sync_ipts_offset = 0.000001; /* one microsecond */

        }

    }

#if defined(AVSYNC_DEBUG)

    static char *action[] = { "drop frame", "copy frame", "dup frame" };

    if (audio_sync)

        fprintf(stderr, "Input APTS %12.6f, output APTS %12.6f, ",

	        (double) audio_sync->sync_ipts,

	        (double) audio_sync->st->pts.val * s->pts_num / s->pts_den);

    fprintf(stderr, "Input VPTS %12.6f, output VPTS %12.6f: %s\n",

            (double) ost->sync_ipts,

  	    (double) ost->st->pts.val * s->pts_num / s->pts_den,

            action[nb_frames]);

#endif

    if (nb_frames <= 0)

        return;

    if (!video_buffer)

        video_buffer = av_malloc(VIDEO_BUFFER_SIZE);

    if (!video_buffer)

        return;

    /* convert pixel format if needed */

    if (enc->pix_fmt != dec->pix_fmt) {

        int size;

        /* create temporary picture */

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

        buf = av_malloc(size);

        if (!buf)

            return;

        formatted_picture = &picture_format_temp;

        avpicture_fill(formatted_picture, buf, enc->pix_fmt, dec->width, dec->height);

        if (img_convert(formatted_picture, enc->pix_fmt,

                        in_picture, dec->pix_fmt,

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

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

            goto the_end;

        }

    } else {

        formatted_picture = in_picture;

    }

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

       some cases to go faster */

    /* XXX: only works for YUV420P */

    if (ost->video_resample) {

        final_picture = &ost->pict_tmp;

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

    } else if (ost->video_crop) {

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

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

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

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

                (ost->leftBand >> 1);

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

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

                (ost->leftBand >> 1);

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

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

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

        final_picture = &picture_crop_temp;

    } else {

        final_picture = formatted_picture;

    }

    /* duplicates frame if needed */

    /* XXX: pb because no interleaving */

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

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

            /* raw pictures are written as AVPicture structure to

               avoid any copies. We support temorarily the older

               method. */

            av_write_frame(s, ost->index,

                           (uint8_t *)final_picture, sizeof(AVPicture));

        } else {

            AVFrame big_picture;

            memset(&big_picture, 0, sizeof(AVFrame));

            *(AVPicture*)&big_picture= *final_picture;

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

               not be a global option */

            if (same_quality) {

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

            }else

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

            ret = avcodec_encode_video(enc,

                                       video_buffer, VIDEO_BUFFER_SIZE,

                                       &big_picture);

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

            av_write_frame(s, ost->index, video_buffer, ret);

            *frame_size = ret;

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

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

            //        enc->pict_type);

            /* if two pass, output log */

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

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

            }

        }

        ost->frame_number++;

    }

 the_end:

    av_free(buf);

    av_free(buf1);

}


static int read_seek(AVFormatContext *s, int stream_index,

                     int64_t pts, int flags)

{

    NUTContext *nut    = s->priv_data;

    AVStream *st       = s->streams[stream_index];

    Syncpoint dummy    = { .ts = pts * av_q2d(st->time_base) * AV_TIME_BASE };

    Syncpoint nopts_sp = { .ts = AV_NOPTS_VALUE, .back_ptr = AV_NOPTS_VALUE };

    Syncpoint *sp, *next_node[2] = { &nopts_sp, &nopts_sp };

    int64_t pos, pos2, ts;

    int i;

    if (nut->flags & NUT_PIPE) {

        return AVERROR(ENOSYS);

    }

    if (st->index_entries) {

        int index = av_index_search_timestamp(st, pts, flags);

        if (index < 0)

            index = av_index_search_timestamp(st, pts, flags ^ AVSEEK_FLAG_BACKWARD);

        if (index < 0)

            return -1;

        pos2 = st->index_entries[index].pos;

        ts   = st->index_entries[index].timestamp;

    } else {

        av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pts_cmp,

                     (void **) next_node);

        av_log(s, AV_LOG_DEBUG, "%"PRIu64"-%"PRIu64" %"PRId64"-%"PRId64"\n",

               next_node[0]->pos, next_node[1]->pos, next_node[0]->ts,

               next_node[1]->ts);

        pos = ff_gen_search(s, -1, dummy.ts, next_node[0]->pos,

                            next_node[1]->pos, next_node[1]->pos,

                            next_node[0]->ts, next_node[1]->ts,

                            AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp);

        if (!(flags & AVSEEK_FLAG_BACKWARD)) {

            dummy.pos    = pos + 16;

            next_node[1] = &nopts_sp;

            av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,

                         (void **) next_node);

            pos2 = ff_gen_search(s, -2, dummy.pos, next_node[0]->pos,

                                 next_node[1]->pos, next_node[1]->pos,

                                 next_node[0]->back_ptr, next_node[1]->back_ptr,

                                 flags, &ts, nut_read_timestamp);

            if (pos2 >= 0)

                pos = pos2;

            // FIXME dir but I think it does not matter

        }

        dummy.pos = pos;

        sp = av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,

                          NULL);

        av_assert0(sp);

        pos2 = sp->back_ptr - 15;

    }

    av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);

    pos = find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2);

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

    nut->last_syncpoint_pos = pos;

    av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);

    if (pos2 > pos || pos2 + 15 < pos)

        av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");

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

        nut->stream[i].skip_until_key_frame = 1;

    nut->last_resync_pos = 0;

    return 0;

}


static QList *get_cpus(QDict **resp)

{

    *resp = qmp("{ 'execute': 'query-cpus' }");

    g_assert(*resp);

    g_assert(qdict_haskey(*resp, "return"));

    return  qdict_get_qlist(*resp, "return");

}


QemuOptsList *qemu_opts_append(QemuOptsList *dst,

                               QemuOptsList *list)

{

    size_t num_opts, num_dst_opts;

    QemuOptDesc *desc;

    bool need_init = false;

    if (!list) {

        return dst;

    }

    /* If dst is NULL, after realloc, some area of dst should be initialized

     * before adding options to it.

     */

    if (!dst) {

        need_init = true;

    }

    num_opts = count_opts_list(dst);

    num_dst_opts = num_opts;

    num_opts += count_opts_list(list);

    dst = g_realloc(dst, sizeof(QemuOptsList) +

                    (num_opts + 1) * sizeof(QemuOptDesc));

    if (need_init) {

        dst->name = NULL;

        dst->implied_opt_name = NULL;

        QTAILQ_INIT(&dst->head);

        dst->merge_lists = false;

    }

    dst->desc[num_dst_opts].name = NULL;

    /* append list->desc to dst->desc */

    if (list) {

        desc = list->desc;

        while (desc && desc->name) {

            if (find_desc_by_name(dst->desc, desc->name) == NULL) {

                dst->desc[num_dst_opts++] = *desc;

                dst->desc[num_dst_opts].name = NULL;

            }

            desc++;

        }

    }

    return dst;

}


static void vnc_dpy_setdata(DisplayChangeListener *dcl,

                            DisplayState *ds)

{

    VncDisplay *vd = ds->opaque;

    qemu_pixman_image_unref(vd->guest.fb);

    vd->guest.fb = pixman_image_ref(ds->surface->image);

    vd->guest.format = ds->surface->format;

    vnc_dpy_update(dcl, ds, 0, 0, ds_get_width(ds), ds_get_height(ds));

}


static inline int cris_addc(int a, const int b)

{

	asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));

	return a;

}


void acpi_setup(PcGuestInfo *guest_info)

{

    AcpiBuildTables tables;

    AcpiBuildState *build_state;

    if (!guest_info->fw_cfg) {

        ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");

        return;

    }

    if (!guest_info->has_acpi_build) {

        ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n");

        return;

    }

    if (!acpi_enabled) {

        ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");

        return;

    }

    build_state = g_malloc0(sizeof *build_state);

    build_state->guest_info = guest_info;

    acpi_set_pci_info();

    acpi_build_tables_init(&tables);

    acpi_build(build_state->guest_info, &tables);

    /* Now expose it all to Guest */

    build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data,

                                               ACPI_BUILD_TABLE_FILE,

                                               ACPI_BUILD_TABLE_MAX_SIZE);

    assert(build_state->table_ram != RAM_ADDR_MAX);

    build_state->table_size = acpi_data_len(tables.table_data);

    acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader", 0);

    fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,

                    tables.tcpalog->data, acpi_data_len(tables.tcpalog));

    /*

     * RSDP is small so it's easy to keep it immutable, no need to

     * bother with ROM blobs.

     */

    fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,

                    tables.rsdp->data, acpi_data_len(tables.rsdp));

    qemu_register_reset(acpi_build_reset, build_state);

    acpi_build_reset(build_state);

    vmstate_register(NULL, 0, &vmstate_acpi_build, build_state);

    /* Cleanup tables but don't free the memory: we track it

     * in build_state.

     */

    acpi_build_tables_cleanup(&tables, false);

}


static void reset_used_window(DisasContext *dc)

{

    dc->used_window = 0;

}


static int decode_block(MJpegDecodeContext *s, int16_t *block, int component,

                        int dc_index, int ac_index, uint16_t *quant_matrix)

{

    int code, i, j, level, val;

    /* DC coef */

    val = mjpeg_decode_dc(s, dc_index);

    if (val == 0xfffff) {

        av_log(s->avctx, AV_LOG_ERROR, "error dc\n");

        return AVERROR_INVALIDDATA;

    }

    val = val * quant_matrix[0] + s->last_dc[component];

    val = FFMIN(val, 32767);

    s->last_dc[component] = val;

    block[0] = val;

    /* AC coefs */

    i = 0;

    {OPEN_READER(re, &s->gb);

    do {

        UPDATE_CACHE(re, &s->gb);

        GET_VLC(code, re, &s->gb, s->vlcs[1][ac_index].table, 9, 2);

        i += ((unsigned)code) >> 4;

            code &= 0xf;

        if (code) {

            if (code > MIN_CACHE_BITS - 16)

                UPDATE_CACHE(re, &s->gb);

            {

                int cache = GET_CACHE(re, &s->gb);

                int sign  = (~cache) >> 31;

                level     = (NEG_USR32(sign ^ cache,code) ^ sign) - sign;

            }

            LAST_SKIP_BITS(re, &s->gb, code);

            if (i > 63) {

                av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i);

                return AVERROR_INVALIDDATA;

            }

            j        = s->scantable.permutated[i];

            block[j] = level * quant_matrix[i];

        }

    } while (i < 63);

    CLOSE_READER(re, &s->gb);}

    return 0;

}


static int usb_host_scan(void *opaque, USBScanFunc *func)

{

    FILE *f = 0;

    DIR *dir = 0;

    int ret = 0;

    const char *devices = "/devices";

    const char *opened = "husb: opened %s%s\n";

    const char *fs_type[] = {"unknown", "proc", "dev", "sys"};

    char devpath[PATH_MAX];

    /* only check the host once */

    if (!usb_fs_type) {

        f = fopen(USBPROCBUS_PATH "/devices", "r");

        if (f) {

            /* devices found in /proc/bus/usb/ */

            strcpy(devpath, USBPROCBUS_PATH);

            usb_fs_type = USB_FS_PROC;

            fclose(f);

            dprintf(opened, USBPROCBUS_PATH, devices);

        }

        /* try additional methods if an access method hasn't been found yet */

        f = fopen(USBDEVBUS_PATH "/devices", "r");

        if (!usb_fs_type && f) {

            /* devices found in /dev/bus/usb/ */

            strcpy(devpath, USBDEVBUS_PATH);

            usb_fs_type = USB_FS_DEV;

            fclose(f);

            dprintf(opened, USBDEVBUS_PATH, devices);

        }

        dir = opendir(USBSYSBUS_PATH "/devices");

        if (!usb_fs_type && dir) {

            /* devices found in /dev/bus/usb/ (yes - not a mistake!) */

            strcpy(devpath, USBDEVBUS_PATH);

            usb_fs_type = USB_FS_SYS;

            closedir(dir);

            dprintf(opened, USBSYSBUS_PATH, devices);

        }

        if (!usb_fs_type) {

            term_printf("husb: unable to access USB devices\n");

            goto the_end;

        }

        /* the module setting (used later for opening devices) */

        usb_host_device_path = qemu_mallocz(strlen(devpath)+1);

        if (usb_host_device_path) {

            strcpy(usb_host_device_path, devpath);

            term_printf("husb: using %s file-system with %s\n", fs_type[usb_fs_type], usb_host_device_path);

        } else {

            /* out of memory? */

            perror("husb: unable to allocate memory for device path");

            goto the_end;

        }

    }

    switch (usb_fs_type) {

    case USB_FS_PROC:

    case USB_FS_DEV:

        ret = usb_host_scan_dev(opaque, func);

        break;

    case USB_FS_SYS:

        ret = usb_host_scan_sys(opaque, func);

        break;

    }

 the_end:

    return ret;

}


static void convert_matrix(DSPContext *dsp, int (*qmat)[64], uint16_t (*qmat16)[2][64],

                           const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra)

{

    int qscale;

    int shift=0;

    for(qscale=qmin; qscale<=qmax; qscale++){

        int i;

        if (dsp->fdct == ff_jpeg_fdct_islow

#ifdef FAAN_POSTSCALE

            || dsp->fdct == ff_faandct

#endif

            ) {

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

                const int j= dsp->idct_permutation[i];

                /* 16 <= qscale * quant_matrix[i] <= 7905 */

                /* 19952         <= aanscales[i] * qscale * quant_matrix[i]           <= 249205026 */

                /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */

                /* 3444240       >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */

                qmat[qscale][i] = (int)((uint64_t_C(1) << QMAT_SHIFT) /

                                (qscale * quant_matrix[j]));

            }

        } else if (dsp->fdct == fdct_ifast

#ifndef FAAN_POSTSCALE

                   || dsp->fdct == ff_faandct

#endif

                   ) {

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

                const int j= dsp->idct_permutation[i];

                /* 16 <= qscale * quant_matrix[i] <= 7905 */

                /* 19952         <= aanscales[i] * qscale * quant_matrix[i]           <= 249205026 */

                /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */

                /* 3444240       >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */

                qmat[qscale][i] = (int)((uint64_t_C(1) << (QMAT_SHIFT + 14)) /

                                (aanscales[i] * qscale * quant_matrix[j]));

            }

        } else {

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

                const int j= dsp->idct_permutation[i];

                /* We can safely suppose that 16 <= quant_matrix[i] <= 255

                   So 16           <= qscale * quant_matrix[i]             <= 7905

                   so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905

                   so 32768        >= (1<<19) / (qscale * quant_matrix[i]) >= 67

                */

                qmat[qscale][i] = (int)((uint64_t_C(1) << QMAT_SHIFT) / (qscale * quant_matrix[j]));

//                qmat  [qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]);

                qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[j]);

                if(qmat16[qscale][0][i]==0 || qmat16[qscale][0][i]==128*256) qmat16[qscale][0][i]=128*256-1;

                qmat16[qscale][1][i]= ROUNDED_DIV(bias<<(16-QUANT_BIAS_SHIFT), qmat16[qscale][0][i]);

            }

        }

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

            while(((8191LL * qmat[qscale][i]) >> shift) > INT_MAX){

                shift++;

            }

        }

    }

    if(shift){

        av_log(NULL, AV_LOG_INFO, "Warning, QMAT_SHIFT is larger then %d, overflows possible\n", QMAT_SHIFT - shift);

    }

}


static int process_frame_obj(SANMVideoContext *ctx)
{
    uint16_t codec, top, left, w, h;
    codec = bytestream2_get_le16u(&ctx->gb);
    left  = bytestream2_get_le16u(&ctx->gb);
    top   = bytestream2_get_le16u(&ctx->gb);
    w     = bytestream2_get_le16u(&ctx->gb);
    h     = bytestream2_get_le16u(&ctx->gb);
    if (ctx->width < left + w || ctx->height < top + h) {
        if (av_image_check_size(FFMAX(left + w, ctx->width),
                                FFMAX(top  + h, ctx->height), 0, ctx->avctx) < 0)
        avcodec_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width),
                                           FFMAX(top  + h, ctx->height));
        init_sizes(ctx, FFMAX(left + w, ctx->width),
                        FFMAX(top  + h, ctx->height));
        if (init_buffers(ctx)) {
            av_log(ctx->avctx, AV_LOG_ERROR, "error resizing buffers\n");
            return AVERROR(ENOMEM);
    bytestream2_skip(&ctx->gb, 4);
    av_dlog(ctx->avctx, "subcodec %d\n", codec);
    switch (codec) {
    case 1:
    case 3:
        return old_codec1(ctx, top, left, w, h);
        break;
    case 37:
        return old_codec37(ctx, top, left, w, h);
        break;
    case 47:
        return old_codec47(ctx, top, left, w, h);
        break;
    default:
        avpriv_request_sample(ctx->avctx, "unknown subcodec %d", codec);
        return AVERROR_PATCHWELCOME;


static int tgq_decode_mb(TgqContext *s, AVFrame *frame, int mb_y, int mb_x)

{

    int mode;

    int i;

    int8_t dc[6];

    mode = bytestream2_get_byte(&s->gb);

    if (mode > 12) {

        GetBitContext gb;

        init_get_bits8(&gb, s->gb.buffer, FFMIN(bytestream2_get_bytes_left(&s->gb), mode));

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

            tgq_decode_block(s, s->block[i], &gb);

        tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y);

        bytestream2_skip(&s->gb, mode);

    } else {

        if (mode == 3) {

            memset(dc, bytestream2_get_byte(&s->gb), 4);

            dc[4] = bytestream2_get_byte(&s->gb);

            dc[5] = bytestream2_get_byte(&s->gb);

        } else if (mode == 6) {

            bytestream2_get_buffer(&s->gb, dc, 6);

        } else if (mode == 12) {

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

                dc[i] = bytestream2_get_byte(&s->gb);

                bytestream2_skip(&s->gb, 1);

            }

        } else {

            av_log(s->avctx, AV_LOG_ERROR, "unsupported mb mode %i\n", mode);

            return -1;

        }

        tgq_idct_put_mb_dconly(s, frame, mb_x, mb_y, dc);

    }

    return 0;

}


static void stream_component_close(VideoState *is, int stream_index)

{

    AVFormatContext *ic = is->ic;

    AVCodecContext *avctx;

    if (stream_index < 0 || stream_index >= ic->nb_streams)

        return;

    avctx = ic->streams[stream_index]->codec;

    switch(avctx->codec_type) {

    case AVMEDIA_TYPE_AUDIO:

        packet_queue_abort(&is->audioq);

        SDL_CloseAudio();

        packet_queue_end(&is->audioq);

        av_free_packet(&is->audio_pkt);

        if (is->reformat_ctx)

            av_audio_convert_free(is->reformat_ctx);

        is->reformat_ctx = NULL;

        if (is->rdft) {

            av_rdft_end(is->rdft);

            av_freep(&is->rdft_data);

        }

        break;

    case AVMEDIA_TYPE_VIDEO:

        packet_queue_abort(&is->videoq);

        /* note: we also signal this mutex to make sure we deblock the

           video thread in all cases */

        SDL_LockMutex(is->pictq_mutex);

        SDL_CondSignal(is->pictq_cond);

        SDL_UnlockMutex(is->pictq_mutex);

        SDL_WaitThread(is->video_tid, NULL);

        packet_queue_end(&is->videoq);

        break;

    case AVMEDIA_TYPE_SUBTITLE:

        packet_queue_abort(&is->subtitleq);

        /* note: we also signal this mutex to make sure we deblock the

           video thread in all cases */

        SDL_LockMutex(is->subpq_mutex);

        is->subtitle_stream_changed = 1;

        SDL_CondSignal(is->subpq_cond);

        SDL_UnlockMutex(is->subpq_mutex);

        SDL_WaitThread(is->subtitle_tid, NULL);

        packet_queue_end(&is->subtitleq);

        break;

    default:

        break;

    }

    ic->streams[stream_index]->discard = AVDISCARD_ALL;

    avcodec_close(avctx);

    switch(avctx->codec_type) {

    case AVMEDIA_TYPE_AUDIO:

        is->audio_st = NULL;

        is->audio_stream = -1;

        break;

    case AVMEDIA_TYPE_VIDEO:

        is->video_st = NULL;

        is->video_stream = -1;

        break;

    case AVMEDIA_TYPE_SUBTITLE:

        is->subtitle_st = NULL;

        is->subtitle_stream = -1;

        break;

    default:

        break;

    }

}


void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,

                         int is_write, hwaddr access_len)

{

    if (buffer != bounce.buffer) {

        if (is_write) {

            ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);

            while (access_len) {

                unsigned l;

                l = TARGET_PAGE_SIZE;

                if (l > access_len)

                    l = access_len;

                invalidate_and_set_dirty(addr1, l);

                addr1 += l;

                access_len -= l;

            }

        }

        if (xen_enabled()) {

            xen_invalidate_map_cache_entry(buffer);

        }

        return;

    }

    if (is_write) {

        address_space_write(as, bounce.addr, bounce.buffer, access_len);

    }

    qemu_vfree(bounce.buffer);

    bounce.buffer = NULL;

    cpu_notify_map_clients();

}


static inline void idct4col_put(uint8_t *dest, int line_size, const int16_t *col)

{

    int c0, c1, c2, c3, a0, a1, a2, a3;

    a0 = col[8*0];

    a1 = col[8*2];

    a2 = col[8*4];

    a3 = col[8*6];

    c0 = ((a0 + a2) << (CN_SHIFT - 1)) + (1 << (C_SHIFT - 1));

    c2 = ((a0 - a2) << (CN_SHIFT - 1)) + (1 << (C_SHIFT - 1));

    c1 = a1 * C1 + a3 * C2;

    c3 = a1 * C2 - a3 * C1;

    dest[0] = av_clip_uint8((c0 + c1) >> C_SHIFT);

    dest += line_size;

    dest[0] = av_clip_uint8((c2 + c3) >> C_SHIFT);

    dest += line_size;

    dest[0] = av_clip_uint8((c2 - c3) >> C_SHIFT);

    dest += line_size;

    dest[0] = av_clip_uint8((c0 - c1) >> C_SHIFT);

}


int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,

                                   target_ulong address, int rw,

                                   int access_type)

{

    ppcemb_tlb_t *tlb;

    target_phys_addr_t raddr;

    int i, prot, ret;

    ret = -1;

    raddr = -1;

    for (i = 0; i < env->nb_tlb; i++) {

        tlb = &env->tlb[i].tlbe;

        if (ppcemb_tlb_check(env, tlb, &raddr, address,

                             env->spr[SPR_BOOKE_PID], 1, i) < 0)

            continue;

        if (msr_pr != 0)

            prot = tlb->prot & 0xF;

        else

            prot = (tlb->prot >> 4) & 0xF;

        /* Check the address space */

        if (access_type == ACCESS_CODE) {

            if (msr_ir != (tlb->attr & 1))

                continue;

            ctx->prot = prot;

            if (prot & PAGE_EXEC) {

                ret = 0;

                break;

            }

            ret = -3;

        } else {

            if (msr_dr != (tlb->attr & 1))

                continue;

            ctx->prot = prot;

            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {

                ret = 0;

                break;

            }

            ret = -2;

        }

    }

    if (ret >= 0)

        ctx->raddr = raddr;

    return ret;

}


void fifo_realloc(FifoBuffer *f, int new_size){

    int old_size= f->end - f->buffer;

    if(old_size < new_size){

        uint8_t *old= f->buffer;

        f->buffer= av_realloc(f->buffer, new_size);

        f->rptr += f->buffer - old;

        f->wptr += f->buffer - old;

        if(f->wptr < f->rptr){

            memmove(f->rptr + new_size - old_size, f->rptr, f->buffer + old_size - f->rptr);

            f->rptr += new_size - old_size;

        }

        f->end= f->buffer + new_size;

    }

}


FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime)

{

    JNIEnv *env = NULL;

    FFAMediaCodec *codec = NULL;

    jstring mime_type = NULL;

    codec = av_mallocz(sizeof(FFAMediaCodec));

    if (!codec) {

        return NULL;

    }

    codec->class = &amediacodec_class;

    env = ff_jni_get_env(codec);

    if (!env) {

        av_freep(&codec);

        return NULL;

    }

    if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {

        goto fail;

    }

    mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);

    if (!mime_type) {

        goto fail;

    }

    codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_decoder_by_type_id, mime_type);

    if (ff_jni_exception_check(env, 1, codec) < 0) {

        goto fail;

    }

    codec->object = (*env)->NewGlobalRef(env, codec->object);

    if (!codec->object) {

        goto fail;

    }

    if (codec_init_static_fields(codec) < 0) {

        goto fail;

    }

    if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {

        codec->has_get_i_o_buffer = 1;

    }

    return codec;

fail:

    ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);

    if (mime_type) {

        (*env)->DeleteLocalRef(env, mime_type);

    }

    av_freep(&codec);

    return NULL;

}


int vnc_tls_validate_certificate(VncState *vs)

{

    int ret;

    unsigned int status;

    const gnutls_datum_t *certs;

    unsigned int nCerts, i;

    time_t now;

    VNC_DEBUG("Validating client certificate\n");

    if ((ret = gnutls_certificate_verify_peers2 (vs->tls.session, &status)) < 0) {

        VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));

        return -1;

    }

    if ((now = time(NULL)) == ((time_t)-1)) {

        return -1;

    }

    if (status != 0) {

        if (status & GNUTLS_CERT_INVALID)

            VNC_DEBUG("The certificate is not trusted.\n");

        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)

            VNC_DEBUG("The certificate hasn't got a known issuer.\n");

        if (status & GNUTLS_CERT_REVOKED)

            VNC_DEBUG("The certificate has been revoked.\n");

        if (status & GNUTLS_CERT_INSECURE_ALGORITHM)

            VNC_DEBUG("The certificate uses an insecure algorithm\n");

        return -1;

    } else {

        VNC_DEBUG("Certificate is valid!\n");

    }

    /* Only support x509 for now */

    if (gnutls_certificate_type_get(vs->tls.session) != GNUTLS_CRT_X509)

        return -1;

    if (!(certs = gnutls_certificate_get_peers(vs->tls.session, &nCerts)))

        return -1;

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

        gnutls_x509_crt_t cert;

        VNC_DEBUG ("Checking certificate chain %d\n", i);

        if (gnutls_x509_crt_init (&cert) < 0)

            return -1;

        if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {

            gnutls_x509_crt_deinit (cert);

            return -1;

        }

        if (gnutls_x509_crt_get_expiration_time (cert) < now) {

            VNC_DEBUG("The certificate has expired\n");

            gnutls_x509_crt_deinit (cert);

            return -1;

        }

        if (gnutls_x509_crt_get_activation_time (cert) > now) {

            VNC_DEBUG("The certificate is not yet activated\n");

            gnutls_x509_crt_deinit (cert);

            return -1;

        }

        if (gnutls_x509_crt_get_activation_time (cert) > now) {

            VNC_DEBUG("The certificate is not yet activated\n");

            gnutls_x509_crt_deinit (cert);

            return -1;

        }

        if (i == 0) {

            size_t dnameSize = 1024;

            vs->tls.dname = g_malloc(dnameSize);

        requery:

            if ((ret = gnutls_x509_crt_get_dn (cert, vs->tls.dname, &dnameSize)) != 0) {

                if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {

                    vs->tls.dname = g_realloc(vs->tls.dname, dnameSize);

                    goto requery;

                }

                gnutls_x509_crt_deinit (cert);

                VNC_DEBUG("Cannot get client distinguished name: %s",

                          gnutls_strerror (ret));

                return -1;

            }

            if (vs->vd->tls.x509verify) {

                int allow;

                if (!vs->vd->tls.acl) {

                    VNC_DEBUG("no ACL activated, allowing access");

                    gnutls_x509_crt_deinit (cert);

                    continue;

                }

                allow = qemu_acl_party_is_allowed(vs->vd->tls.acl,

                                                  vs->tls.dname);

                VNC_DEBUG("TLS x509 ACL check for %s is %s\n",

                          vs->tls.dname, allow ? "allowed" : "denied");

                if (!allow) {

                    gnutls_x509_crt_deinit (cert);

                    return -1;

                }

            }

        }

        gnutls_x509_crt_deinit (cert);

    }

    return 0;

}


static void vc1_interp_mc(VC1Context *v)

{

    MpegEncContext *s = &v->s;

    H264ChromaContext *h264chroma = &v->h264chroma;

    uint8_t *srcY, *srcU, *srcV;

    int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y;

    int off, off_uv;

    int v_edge_pos = s->v_edge_pos >> v->field_mode;

    int use_ic = v->next_use_ic;

    if (!v->field_mode && !v->s.next_picture.f.data[0])

        return;

    mx   = s->mv[1][0][0];

    my   = s->mv[1][0][1];

    uvmx = (mx + ((mx & 3) == 3)) >> 1;

    uvmy = (my + ((my & 3) == 3)) >> 1;

    if (v->field_mode) {

        if (v->cur_field_type != v->ref_field_type[1])

            my   = my   - 2 + 4 * v->cur_field_type;

            uvmy = uvmy - 2 + 4 * v->cur_field_type;

    }

    if (v->fastuvmc) {

        uvmx = uvmx + ((uvmx < 0) ? -(uvmx & 1) : (uvmx & 1));

        uvmy = uvmy + ((uvmy < 0) ? -(uvmy & 1) : (uvmy & 1));

    }

    srcY = s->next_picture.f.data[0];

    srcU = s->next_picture.f.data[1];

    srcV = s->next_picture.f.data[2];

    src_x   = s->mb_x * 16 + (mx   >> 2);

    src_y   = s->mb_y * 16 + (my   >> 2);

    uvsrc_x = s->mb_x *  8 + (uvmx >> 2);

    uvsrc_y = s->mb_y *  8 + (uvmy >> 2);

    if (v->profile != PROFILE_ADVANCED) {

        src_x   = av_clip(  src_x, -16, s->mb_width  * 16);

        src_y   = av_clip(  src_y, -16, s->mb_height * 16);

        uvsrc_x = av_clip(uvsrc_x,  -8, s->mb_width  *  8);

        uvsrc_y = av_clip(uvsrc_y,  -8, s->mb_height *  8);

    } else {

        src_x   = av_clip(  src_x, -17, s->avctx->coded_width);

        src_y   = av_clip(  src_y, -18, s->avctx->coded_height + 1);

        uvsrc_x = av_clip(uvsrc_x,  -8, s->avctx->coded_width  >> 1);

        uvsrc_y = av_clip(uvsrc_y,  -8, s->avctx->coded_height >> 1);

    }

    srcY += src_y   * s->linesize   + src_x;

    srcU += uvsrc_y * s->uvlinesize + uvsrc_x;

    srcV += uvsrc_y * s->uvlinesize + uvsrc_x;

    if (v->field_mode && v->ref_field_type[1]) {

        srcY += s->current_picture_ptr->f.linesize[0];

        srcU += s->current_picture_ptr->f.linesize[1];

        srcV += s->current_picture_ptr->f.linesize[2];

    }

    /* for grayscale we should not try to read from unknown area */

    if (s->flags & CODEC_FLAG_GRAY) {

        srcU = s->edge_emu_buffer + 18 * s->linesize;

        srcV = s->edge_emu_buffer + 18 * s->linesize;

    }

    if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 || use_ic

        || (unsigned)(src_x - 1) > s->h_edge_pos - (mx & 3) - 16 - 3

        || (unsigned)(src_y - 1) > v_edge_pos    - (my & 3) - 16 - 3) {

        uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize;

        srcY -= s->mspel * (1 + s->linesize);

        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY,

                                 s->linesize, s->linesize,

                                 17 + s->mspel * 2, 17 + s->mspel * 2,

                                 src_x - s->mspel, src_y - s->mspel,

                                 s->h_edge_pos, v_edge_pos);

        srcY = s->edge_emu_buffer;

        s->vdsp.emulated_edge_mc(uvbuf, srcU,

                                 s->uvlinesize, s->uvlinesize,

                                 8 + 1, 8 + 1,

                                 uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1);

        s->vdsp.emulated_edge_mc(uvbuf + 16, srcV,

                                 s->uvlinesize, s->uvlinesize,

                                 8 + 1, 8 + 1,

                                 uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1);

        srcU = uvbuf;

        srcV = uvbuf + 16;

        /* if we deal with range reduction we need to scale source blocks */

        if (v->rangeredfrm) {

            int i, j;

            uint8_t *src, *src2;

            src = srcY;

            for (j = 0; j < 17 + s->mspel * 2; j++) {

                for (i = 0; i < 17 + s->mspel * 2; i++)

                    src[i] = ((src[i] - 128) >> 1) + 128;

                src += s->linesize;

            }

            src = srcU;

            src2 = srcV;

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

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

                    src[i]  = ((src[i]  - 128) >> 1) + 128;

                    src2[i] = ((src2[i] - 128) >> 1) + 128;

                }

                src  += s->uvlinesize;

                src2 += s->uvlinesize;

            }

        }

        if (use_ic) {

            uint8_t (*luty )[256] = v->next_luty;

            uint8_t (*lutuv)[256] = v->next_lutuv;

            int i, j;

            uint8_t *src, *src2;

            src = srcY;

            for (j = 0; j < 17 + s->mspel * 2; j++) {

                int f = v->field_mode ? v->ref_field_type[1] : ((j+src_y - s->mspel) & 1);

                for (i = 0; i < 17 + s->mspel * 2; i++)

                    src[i] = luty[f][src[i]];

                src += s->linesize;

            }

            src  = srcU;

            src2 = srcV;

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

                int f = v->field_mode ? v->ref_field_type[1] : ((j+uvsrc_y) & 1);

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

                    src[i]  = lutuv[f][src[i]];

                    src2[i] = lutuv[f][src2[i]];

                }

                src  += s->uvlinesize;

                src2 += s->uvlinesize;

            }

        }

        srcY += s->mspel * (1 + s->linesize);

    }

    off    = 0;

    off_uv = 0;

    if (s->mspel) {

        dxy = ((my & 3) << 2) | (mx & 3);

        v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off    , srcY    , s->linesize, v->rnd);

        v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8, srcY + 8, s->linesize, v->rnd);

        srcY += s->linesize * 8;

        v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize    , srcY    , s->linesize, v->rnd);

        v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize + 8, srcY + 8, s->linesize, v->rnd);

    } else { // hpel mc

        dxy = (my & 2) | ((mx & 2) >> 1);

        if (!v->rnd)

            s->hdsp.avg_pixels_tab[0][dxy](s->dest[0] + off, srcY, s->linesize, 16);

        else

            s->hdsp.avg_no_rnd_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize, 16);

    }

    if (s->flags & CODEC_FLAG_GRAY) return;

    /* Chroma MC always uses qpel blilinear */

    uvmx = (uvmx & 3) << 1;

    uvmy = (uvmy & 3) << 1;

    if (!v->rnd) {

        h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy);

        h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy);

    } else {

        v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy);

        v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy);

    }

}


static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,

    bool is_read)

{

    BlockErrorAction action = blk_get_error_action(req->dev->blk,

                                                   is_read, error);

    VirtIOBlock *s = req->dev;

    if (action == BLOCK_ERROR_ACTION_STOP) {

        req->next = s->rq;

        s->rq = req;

    } else if (action == BLOCK_ERROR_ACTION_REPORT) {

        virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);

        block_acct_done(blk_get_stats(s->blk), &req->acct);

        virtio_blk_free_request(req);

    }

    blk_error_action(s->blk, action, is_read, error);

    return action != BLOCK_ERROR_ACTION_IGNORE;

}


static int dnxhd_decode_header(DNXHDContext *ctx, const uint8_t *buf, int buf_size, int first_field)

{

    static const uint8_t header_prefix[] = { 0x00, 0x00, 0x02, 0x80, 0x01 };

    int i, cid;

    if (buf_size < 0x280)

        return -1;

    if (memcmp(buf, header_prefix, 5)) {

        av_log(ctx->avctx, AV_LOG_ERROR, "error in header\n");

        return -1;

    }

    if (buf[5] & 2) { /* interlaced */

        ctx->cur_field = buf[5] & 1;

        ctx->picture.interlaced_frame = 1;

        ctx->picture.top_field_first = first_field ^ ctx->cur_field;

        av_log(ctx->avctx, AV_LOG_DEBUG, "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field);

    }

    ctx->height = AV_RB16(buf + 0x18);

    ctx->width  = AV_RB16(buf + 0x1a);

    av_dlog(ctx->avctx, "width %d, height %d\n", ctx->width, ctx->height);

    if (buf[0x21] & 0x40) {

        ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P10;

        ctx->avctx->bits_per_raw_sample = 10;

        if (ctx->bit_depth != 10) {

            ff_dsputil_init(&ctx->dsp, ctx->avctx);

            ctx->bit_depth = 10;

            ctx->decode_dct_block = dnxhd_decode_dct_block_10;

        }

    } else {

        ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P;

        ctx->avctx->bits_per_raw_sample = 8;

        if (ctx->bit_depth != 8) {

            ff_dsputil_init(&ctx->dsp, ctx->avctx);

            ctx->bit_depth = 8;

            ctx->decode_dct_block = dnxhd_decode_dct_block_8;

        }

    }

    cid = AV_RB32(buf + 0x28);

    av_dlog(ctx->avctx, "compression id %d\n", cid);

    if (dnxhd_init_vlc(ctx, cid) < 0)

        return -1;

    if (buf_size < ctx->cid_table->coding_unit_size) {

        av_log(ctx->avctx, AV_LOG_ERROR, "incorrect frame size\n");

        return -1;

    }

    ctx->mb_width = ctx->width>>4;

    ctx->mb_height = buf[0x16d];

    av_dlog(ctx->avctx, "mb width %d, mb height %d\n", ctx->mb_width, ctx->mb_height);

    if ((ctx->height+15)>>4 == ctx->mb_height && ctx->picture.interlaced_frame)

        ctx->height <<= 1;

    if (ctx->mb_height > 68 ||

        (ctx->mb_height<<ctx->picture.interlaced_frame) > (ctx->height+15)>>4) {

        av_log(ctx->avctx, AV_LOG_ERROR, "mb height too big: %d\n", ctx->mb_height);

        return -1;

    }

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

        ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i<<2));

        av_dlog(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]);

        if (buf_size < ctx->mb_scan_index[i] + 0x280) {

            av_log(ctx->avctx, AV_LOG_ERROR, "invalid mb scan index\n");

            return -1;

        }

    }

    return 0;

}


static int ogg_write_trailer(AVFormatContext *s)

{

    int i;

    /* flush current page */

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

        ogg_buffer_page(s, s->streams[i]->priv_data);

    ogg_write_pages(s, 1);

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

        AVStream *st = s->streams[i];

        OGGStreamContext *oggstream = st->priv_data;

        if (st->codec->codec_id == CODEC_ID_FLAC ||

            st->codec->codec_id == CODEC_ID_SPEEX) {

            av_free(oggstream->header[0]);

        }

        av_freep(&st->priv_data);

    }

    return 0;

}


static void do_inject_mce(Monitor *mon, const QDict *qdict)

{

    CPUState *cenv;

    int cpu_index = qdict_get_int(qdict, "cpu_index");

    int bank = qdict_get_int(qdict, "bank");

    uint64_t status = qdict_get_int(qdict, "status");

    uint64_t mcg_status = qdict_get_int(qdict, "mcg_status");

    uint64_t addr = qdict_get_int(qdict, "addr");

    uint64_t misc = qdict_get_int(qdict, "misc");

    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu)

        if (cenv->cpu_index == cpu_index && cenv->mcg_cap) {

            cpu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);

            break;

        }

}


static int avi_sync(AVFormatContext *s, int exit_early)

{

    AVIContext *avi = s->priv_data;

    AVIOContext *pb = s->pb;

    int n;

    unsigned int d[8];

    unsigned int size;

    int64_t i, sync;

start_sync:

    memset(d, -1, sizeof(d));

    for (i = sync = avio_tell(pb); !avio_feof(pb); i++) {

        int j;

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

            d[j] = d[j + 1];

        d[7] = avio_r8(pb);

        size = d[4] + (d[5] << 8) + (d[6] << 16) + (d[7] << 24);

        n = get_stream_idx(d + 2);

        ff_tlog(s, "%X %X %X %X %X %X %X %X %"PRId64" %u %d\n",

                d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n);

        if (i*(avi->io_fsize>0) + (uint64_t)size > avi->fsize || d[0] > 127)

            continue;

        // parse ix##

        if ((d[0] == 'i' && d[1] == 'x' && n < s->nb_streams) ||

            // parse JUNK

            (d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K') ||

            (d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1') ||

            (d[0] == 'i' && d[1] == 'n' && d[2] == 'd' && d[3] == 'x')) {

            avio_skip(pb, size);

            goto start_sync;

        }

        // parse stray LIST

        if (d[0] == 'L' && d[1] == 'I' && d[2] == 'S' && d[3] == 'T') {

            avio_skip(pb, 4);

            goto start_sync;

        }

        n = get_stream_idx(d);

        if (!((i - avi->last_pkt_pos) & 1) &&

            get_stream_idx(d + 1) < s->nb_streams)

            continue;

        // detect ##ix chunk and skip

        if (d[2] == 'i' && d[3] == 'x' && n < s->nb_streams) {

            avio_skip(pb, size);

            goto start_sync;

        }

        if (avi->dv_demux && n != 0)

            continue;

        // parse ##dc/##wb

        if (n < s->nb_streams) {

            AVStream *st;

            AVIStream *ast;

            st  = s->streams[n];

            ast = st->priv_data;

            if (!ast) {

                av_log(s, AV_LOG_WARNING, "Skipping foreign stream %d packet\n", n);

                continue;

            }

            if (s->nb_streams >= 2) {

                AVStream *st1   = s->streams[1];

                AVIStream *ast1 = st1->priv_data;

                // workaround for broken small-file-bug402.avi

                if (   d[2] == 'w' && d[3] == 'b'

                   && n == 0

                   && st ->codecpar->codec_type == AVMEDIA_TYPE_VIDEO

                   && st1->codecpar->codec_type == AVMEDIA_TYPE_AUDIO

                   && ast->prefix == 'd'*256+'c'

                   && (d[2]*256+d[3] == ast1->prefix || !ast1->prefix_count)

                  ) {

                    n   = 1;

                    st  = st1;

                    ast = ast1;

                    av_log(s, AV_LOG_WARNING,

                           "Invalid stream + prefix combination, assuming audio.\n");

                }

            }

            if (!avi->dv_demux &&

                ((st->discard >= AVDISCARD_DEFAULT && size == 0) /* ||

                 // FIXME: needs a little reordering

                 (st->discard >= AVDISCARD_NONKEY &&

                 !(pkt->flags & AV_PKT_FLAG_KEY)) */

                || st->discard >= AVDISCARD_ALL)) {

                if (!exit_early) {

                    ast->frame_offset += get_duration(ast, size);

                    avio_skip(pb, size);

                    goto start_sync;

                }

            }

            if (d[2] == 'p' && d[3] == 'c' && size <= 4 * 256 + 4) {

                int k    = avio_r8(pb);

                int last = (k + avio_r8(pb) - 1) & 0xFF;

                avio_rl16(pb); // flags

                // b + (g << 8) + (r << 16);

                for (; k <= last; k++)

                    ast->pal[k] = 0xFFU<<24 | avio_rb32(pb)>>8;

                ast->has_pal = 1;

                goto start_sync;

            } else if (((ast->prefix_count < 5 || sync + 9 > i) &&

                        d[2] < 128 && d[3] < 128) ||

                       d[2] * 256 + d[3] == ast->prefix /* ||

                       (d[2] == 'd' && d[3] == 'c') ||

                       (d[2] == 'w' && d[3] == 'b') */) {

                if (exit_early)

                    return 0;

                if (d[2] * 256 + d[3] == ast->prefix)

                    ast->prefix_count++;

                else {

                    ast->prefix       = d[2] * 256 + d[3];

                    ast->prefix_count = 0;

                }

                avi->stream_index = n;

                ast->packet_size  = size + 8;

                ast->remaining    = size;

                if (size) {

                    uint64_t pos = avio_tell(pb) - 8;

                    if (!st->index_entries || !st->nb_index_entries ||

                        st->index_entries[st->nb_index_entries - 1].pos < pos) {

                        av_add_index_entry(st, pos, ast->frame_offset, size,

                                           0, AVINDEX_KEYFRAME);

                    }

                }

                return 0;

            }

        }

    }

    if (pb->error)

        return pb->error;

    return AVERROR_EOF;

}


static int roq_probe(AVProbeData *p)

{

    if (p->buf_size < 6)

        return 0;

    if ((AV_RL16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||

        (AV_RL32(&p->buf[2]) != 0xFFFFFFFF))

        return 0;

    return AVPROBE_SCORE_MAX;

}


inline static void RENAME(hcscale)(SwsContext *c, uint16_t *dst, long dstWidth, const uint8_t *src1, const uint8_t *src2,

                                   int srcW, int xInc, const int16_t *hChrFilter,

                                   const int16_t *hChrFilterPos, int hChrFilterSize,

                                   uint8_t *formatConvBuffer,

                                   uint32_t *pal)

{

    src1 += c->chrSrcOffset;

    src2 += c->chrSrcOffset;

    if (c->chrToYV12) {

        c->chrToYV12(formatConvBuffer, formatConvBuffer+VOFW, src1, src2, srcW, pal);

        src1= formatConvBuffer;

        src2= formatConvBuffer+VOFW;

    }

    if (c->hScale16) {

        c->hScale16(dst     , dstWidth, (uint16_t*)src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1);

        c->hScale16(dst+VOFW, dstWidth, (uint16_t*)src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1);

    } else if (!c->hcscale_fast) {

        c->hScale(dst     , dstWidth, src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);

        c->hScale(dst+VOFW, dstWidth, src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);

    } else { // fast bilinear upscale / crap downscale

        c->hcscale_fast(c, dst, dstWidth, src1, src2, srcW, xInc);

    }

    if (c->chrConvertRange)

        c->chrConvertRange(dst, dstWidth);

}


static int net_init_nic(QemuOpts *opts, const char *name, VLANState *vlan)

{

    int idx;

    NICInfo *nd;

    const char *netdev;

    idx = nic_get_free_idx();

    if (idx == -1 || nb_nics >= MAX_NICS) {

        error_report("Too Many NICs");

        return -1;

    }

    nd = &nd_table[idx];

    memset(nd, 0, sizeof(*nd));

    if ((netdev = qemu_opt_get(opts, "netdev"))) {

        nd->netdev = qemu_find_netdev(netdev);

        if (!nd->netdev) {

            error_report("netdev '%s' not found", netdev);

            return -1;

        }

    } else {

        assert(vlan);

        nd->vlan = vlan;

    }

    if (name) {

        nd->name = g_strdup(name);

    }

    if (qemu_opt_get(opts, "model")) {

        nd->model = g_strdup(qemu_opt_get(opts, "model"));

    }

    if (qemu_opt_get(opts, "addr")) {

        nd->devaddr = g_strdup(qemu_opt_get(opts, "addr"));

    }

    if (qemu_opt_get(opts, "macaddr") &&

        net_parse_macaddr(nd->macaddr.a, qemu_opt_get(opts, "macaddr")) < 0) {

        error_report("invalid syntax for ethernet address");

        return -1;

    }

    qemu_macaddr_default_if_unset(&nd->macaddr);

    nd->nvectors = qemu_opt_get_number(opts, "vectors",

                                       DEV_NVECTORS_UNSPECIFIED);

    if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&

        (nd->nvectors < 0 || nd->nvectors > 0x7ffffff)) {

        error_report("invalid # of vectors: %d", nd->nvectors);

        return -1;

    }

    nd->used = 1;

    nb_nics++;

    return idx;

}


void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts,

                        int *duration)

{

    int64_t out_pts = AV_NOPTS_VALUE;

    int removed_samples = 0;

    int i;

    if (afq->frame_count || afq->frame_alloc) {

        if (afq->frames->pts != AV_NOPTS_VALUE)

            out_pts = afq->frames->pts;

    }

    if(!afq->frame_count)

        av_log(afq->avctx, AV_LOG_WARNING, "Trying to remove %d samples, but que empty\n", nb_samples);

    if (pts)

        *pts = ff_samples_to_time_base(afq->avctx, out_pts);

    for(i=0; nb_samples && i<afq->frame_count; i++){

        int n= FFMIN(afq->frames[i].duration, nb_samples);

        afq->frames[i].duration -= n;

        nb_samples              -= n;

        removed_samples         += n;

        if(afq->frames[i].pts != AV_NOPTS_VALUE)

            afq->frames[i].pts      += n;

    }

    i -= i && afq->frames[i-1].duration;

    memmove(afq->frames, afq->frames + i, sizeof(*afq->frames) * (afq->frame_count - i));

    afq->frame_count -= i;

    if(nb_samples){

        av_assert0(!afq->frame_count);

        if(afq->frames[0].pts != AV_NOPTS_VALUE)

            afq->frames[0].pts += nb_samples;

        av_log(afq->avctx, AV_LOG_DEBUG, "Trying to remove %d more samples than are in the que\n", nb_samples);

    }

    if (duration)

        *duration = ff_samples_to_time_base(afq->avctx, removed_samples);

}


static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)

{

    QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;

    uint32_t data;

    if (dev->pdev->msix_enabled) {

        g_assert_cmpint(dev->config_msix_entry, !=, -1);

        if (qpci_msix_masked(dev->pdev, dev->config_msix_entry)) {

            /* No ISR checking should be done if masked, but read anyway */

            return qpci_msix_pending(dev->pdev, dev->config_msix_entry);

        } else {

            data = readl(dev->config_msix_addr);

            writel(dev->config_msix_addr, 0);

            return data == dev->config_msix_data;

        }

    } else {

        return qpci_io_readb(dev->pdev, dev->addr + QVIRTIO_PCI_ISR_STATUS) & 2;

    }

}


static int do_pcie_aer_inject_error(Monitor *mon,

                                    const QDict *qdict, QObject **ret_data)

{

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

    const char *error_name;

    uint32_t error_status;

    bool correctable;

    PCIDevice *dev;

    PCIEAERErr err;

    int ret;

    ret = pci_qdev_find_device(id, &dev);

    if (ret < 0) {

        monitor_printf(mon,

                       "id or pci device path is invalid or device not "

                       "found. %s\n", id);

        return ret;

    }

    if (!pci_is_express(dev)) {

        monitor_printf(mon, "the device doesn't support pci express. %s\n",

                       id);

        return -ENOSYS;

    }

    error_name = qdict_get_str(qdict, "error_status");

    if (pcie_aer_parse_error_string(error_name, &error_status, &correctable)) {

        char *e = NULL;

        error_status = strtoul(error_name, &e, 0);

        correctable = qdict_get_try_bool(qdict, "correctable", false);

        if (!e || *e != '\0') {

            monitor_printf(mon, "invalid error status value. \"%s\"",

                           error_name);

            return -EINVAL;

        }

    }

    err.status = error_status;

    err.source_id = pci_requester_id(dev);

    err.flags = 0;

    if (correctable) {

        err.flags |= PCIE_AER_ERR_IS_CORRECTABLE;

    }

    if (qdict_get_try_bool(qdict, "advisory_non_fatal", false)) {

        err.flags |= PCIE_AER_ERR_MAYBE_ADVISORY;

    }

    if (qdict_haskey(qdict, "header0")) {

        err.flags |= PCIE_AER_ERR_HEADER_VALID;

    }

    if (qdict_haskey(qdict, "prefix0")) {

        err.flags |= PCIE_AER_ERR_TLP_PREFIX_PRESENT;

    }

    err.header[0] = qdict_get_try_int(qdict, "header0", 0);

    err.header[1] = qdict_get_try_int(qdict, "header1", 0);

    err.header[2] = qdict_get_try_int(qdict, "header2", 0);

    err.header[3] = qdict_get_try_int(qdict, "header3", 0);

    err.prefix[0] = qdict_get_try_int(qdict, "prefix0", 0);

    err.prefix[1] = qdict_get_try_int(qdict, "prefix1", 0);

    err.prefix[2] = qdict_get_try_int(qdict, "prefix2", 0);

    err.prefix[3] = qdict_get_try_int(qdict, "prefix3", 0);

    ret = pcie_aer_inject_error(dev, &err);

    *ret_data = qobject_from_jsonf("{'id': %s, "

                                   "'root_bus': %s, 'bus': %d, 'devfn': %d, "

                                   "'ret': %d}",

                                   id, pci_root_bus_path(dev),

                                   pci_bus_num(dev->bus), dev->devfn,

                                   ret);

    assert(*ret_data);

    return 0;

}


static int bmp_decode_frame(AVCodecContext *avctx,

                            void *data, int *got_frame,

                            AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data;

    int buf_size       = avpkt->size;

    AVFrame *p         = data;

    unsigned int fsize, hsize;

    int width, height;

    unsigned int depth;

    BiCompression comp;

    unsigned int ihsize;

    int i, j, n, linesize, ret;

    uint32_t rgb[3] = {0};

    uint32_t alpha = 0;

    uint8_t *ptr;

    int dsize;

    const uint8_t *buf0 = buf;

    GetByteContext gb;

    if (buf_size < 14) {

        av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);

        return AVERROR_INVALIDDATA;

    }

    if (bytestream_get_byte(&buf) != 'B' ||

        bytestream_get_byte(&buf) != 'M') {

        av_log(avctx, AV_LOG_ERROR, "bad magic number\n");

        return AVERROR_INVALIDDATA;

    }

    fsize = bytestream_get_le32(&buf);

    if (buf_size < fsize) {

        av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %u), trying to decode anyway\n",

               buf_size, fsize);

        fsize = buf_size;

    }

    buf += 2; /* reserved1 */

    buf += 2; /* reserved2 */

    hsize  = bytestream_get_le32(&buf); /* header size */

    ihsize = bytestream_get_le32(&buf); /* more header size */

    if (ihsize + 14LL > hsize) {

        av_log(avctx, AV_LOG_ERROR, "invalid header size %u\n", hsize);

        return AVERROR_INVALIDDATA;

    }

    /* sometimes file size is set to some headers size, set a real size in that case */

    if (fsize == 14 || fsize == ihsize + 14)

        fsize = buf_size - 2;

    if (fsize <= hsize) {

        av_log(avctx, AV_LOG_ERROR,

               "Declared file size is less than header size (%u < %u)\n",

               fsize, hsize);

        return AVERROR_INVALIDDATA;

    }

    switch (ihsize) {

    case  40: // windib

    case  56: // windib v3

    case  64: // OS/2 v2

    case 108: // windib v4

    case 124: // windib v5

        width  = bytestream_get_le32(&buf);

        height = bytestream_get_le32(&buf);

        break;

    case  12: // OS/2 v1

        width  = bytestream_get_le16(&buf);

        height = bytestream_get_le16(&buf);

        break;

    default:

        avpriv_report_missing_feature(avctx, "Information header size %u",

                                      ihsize);

        return AVERROR_PATCHWELCOME;

    }

    /* planes */

    if (bytestream_get_le16(&buf) != 1) {

        av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n");

        return AVERROR_INVALIDDATA;

    }

    depth = bytestream_get_le16(&buf);

    if (ihsize >= 40)

        comp = bytestream_get_le32(&buf);

    else

        comp = BMP_RGB;

    if (comp != BMP_RGB && comp != BMP_BITFIELDS && comp != BMP_RLE4 &&

        comp != BMP_RLE8) {

        av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp);

        return AVERROR_INVALIDDATA;

    }

    if (comp == BMP_BITFIELDS) {

        buf += 20;

        rgb[0] = bytestream_get_le32(&buf);

        rgb[1] = bytestream_get_le32(&buf);

        rgb[2] = bytestream_get_le32(&buf);

        if (ihsize > 40)

        alpha = bytestream_get_le32(&buf);

    }

    avctx->width  = width;

    avctx->height = height > 0 ? height : -(unsigned)height;

    avctx->pix_fmt = AV_PIX_FMT_NONE;

    switch (depth) {

    case 32:

        if (comp == BMP_BITFIELDS) {

            if (rgb[0] == 0xFF000000 && rgb[1] == 0x00FF0000 && rgb[2] == 0x0000FF00)

                avctx->pix_fmt = alpha ? AV_PIX_FMT_ABGR : AV_PIX_FMT_0BGR;

            else if (rgb[0] == 0x00FF0000 && rgb[1] == 0x0000FF00 && rgb[2] == 0x000000FF)

                avctx->pix_fmt = alpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_BGR0;

            else if (rgb[0] == 0x0000FF00 && rgb[1] == 0x00FF0000 && rgb[2] == 0xFF000000)

                avctx->pix_fmt = alpha ? AV_PIX_FMT_ARGB : AV_PIX_FMT_0RGB;

            else if (rgb[0] == 0x000000FF && rgb[1] == 0x0000FF00 && rgb[2] == 0x00FF0000)

                avctx->pix_fmt = alpha ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB0;

            else {

                av_log(avctx, AV_LOG_ERROR, "Unknown bitfields "

                       "%0"PRIX32" %0"PRIX32" %0"PRIX32"\n", rgb[0], rgb[1], rgb[2]);

                return AVERROR(EINVAL);

            }

        } else {

            avctx->pix_fmt = AV_PIX_FMT_BGRA;

        }

        break;

    case 24:

        avctx->pix_fmt = AV_PIX_FMT_BGR24;

        break;

    case 16:

        if (comp == BMP_RGB)

            avctx->pix_fmt = AV_PIX_FMT_RGB555;

        else if (comp == BMP_BITFIELDS) {

            if (rgb[0] == 0xF800 && rgb[1] == 0x07E0 && rgb[2] == 0x001F)

               avctx->pix_fmt = AV_PIX_FMT_RGB565;

            else if (rgb[0] == 0x7C00 && rgb[1] == 0x03E0 && rgb[2] == 0x001F)

               avctx->pix_fmt = AV_PIX_FMT_RGB555;

            else if (rgb[0] == 0x0F00 && rgb[1] == 0x00F0 && rgb[2] == 0x000F)

               avctx->pix_fmt = AV_PIX_FMT_RGB444;

            else {

               av_log(avctx, AV_LOG_ERROR,

                      "Unknown bitfields %0"PRIX32" %0"PRIX32" %0"PRIX32"\n",

                      rgb[0], rgb[1], rgb[2]);

               return AVERROR(EINVAL);

            }

        }

        break;

    case 8:

        if (hsize - ihsize - 14 > 0)

            avctx->pix_fmt = AV_PIX_FMT_PAL8;

        else

            avctx->pix_fmt = AV_PIX_FMT_GRAY8;

        break;

    case 1:

    case 4:

        if (hsize - ihsize - 14 > 0) {

            avctx->pix_fmt = AV_PIX_FMT_PAL8;

        } else {

            av_log(avctx, AV_LOG_ERROR, "Unknown palette for %u-colour BMP\n",

                   1 << depth);

            return AVERROR_INVALIDDATA;

        }

        break;

    default:

        av_log(avctx, AV_LOG_ERROR, "depth %u not supported\n", depth);

        return AVERROR_INVALIDDATA;

    }

    if (avctx->pix_fmt == AV_PIX_FMT_NONE) {

        av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");

        return AVERROR_INVALIDDATA;

    }

    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)

        return ret;

    p->pict_type = AV_PICTURE_TYPE_I;

    p->key_frame = 1;

    buf   = buf0 + hsize;

    dsize = buf_size - hsize;

    /* Line size in file multiple of 4 */

    n = ((avctx->width * depth + 31) / 8) & ~3;

    if (n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8) {

        n = (avctx->width * depth + 7) / 8;

        if (n * avctx->height > dsize) {

            av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n",

                   dsize, n * avctx->height);

            return AVERROR_INVALIDDATA;

        }

        av_log(avctx, AV_LOG_ERROR, "data size too small, assuming missing line alignment\n");

    }

    // RLE may skip decoding some picture areas, so blank picture before decoding

    if (comp == BMP_RLE4 || comp == BMP_RLE8)

        memset(p->data[0], 0, avctx->height * p->linesize[0]);

    if (height > 0) {

        ptr      = p->data[0] + (avctx->height - 1) * p->linesize[0];

        linesize = -p->linesize[0];

    } else {

        ptr      = p->data[0];

        linesize = p->linesize[0];

    }

    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {

        int colors = 1 << depth;

        memset(p->data[1], 0, 1024);

        if (ihsize >= 36) {

            int t;

            buf = buf0 + 46;

            t   = bytestream_get_le32(&buf);

            if (t < 0 || t > (1 << depth)) {

                av_log(avctx, AV_LOG_ERROR,

                       "Incorrect number of colors - %X for bitdepth %u\n",

                       t, depth);

            } else if (t) {

                colors = t;

            }

        } else {

            colors = FFMIN(256, (hsize-ihsize-14) / 3);

        }

        buf = buf0 + 14 + ihsize; //palette location

        // OS/2 bitmap, 3 bytes per palette entry

        if ((hsize-ihsize-14) < (colors << 2)) {

            if ((hsize-ihsize-14) < colors * 3) {

                av_log(avctx, AV_LOG_ERROR, "palette doesn't fit in packet\n");

                return AVERROR_INVALIDDATA;

            }

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

                ((uint32_t*)p->data[1])[i] = (0xFFU<<24) | bytestream_get_le24(&buf);

        } else {

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

                ((uint32_t*)p->data[1])[i] = 0xFFU << 24 | bytestream_get_le32(&buf);

        }

        buf = buf0 + hsize;

    }

    if (comp == BMP_RLE4 || comp == BMP_RLE8) {

        if (comp == BMP_RLE8 && height < 0) {

            p->data[0]    +=  p->linesize[0] * (avctx->height - 1);

            p->linesize[0] = -p->linesize[0];

        }

        bytestream2_init(&gb, buf, dsize);

        ff_msrle_decode(avctx, p, depth, &gb);

        if (height < 0) {

            p->data[0]    +=  p->linesize[0] * (avctx->height - 1);

            p->linesize[0] = -p->linesize[0];

        }

    } else {

        switch (depth) {

        case 1:

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

                int j;

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

                    ptr[j*8+0] =  buf[j] >> 7;

                    ptr[j*8+1] = (buf[j] >> 6) & 1;

                    ptr[j*8+2] = (buf[j] >> 5) & 1;

                    ptr[j*8+3] = (buf[j] >> 4) & 1;

                    ptr[j*8+4] = (buf[j] >> 3) & 1;

                    ptr[j*8+5] = (buf[j] >> 2) & 1;

                    ptr[j*8+6] = (buf[j] >> 1) & 1;

                    ptr[j*8+7] =  buf[j]       & 1;

                }

                buf += n;

                ptr += linesize;

            }

            break;

        case 8:

        case 24:

        case 32:

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

                memcpy(ptr, buf, n);

                buf += n;

                ptr += linesize;

            }

            break;

        case 4:

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

                int j;

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

                    ptr[j*2+0] = (buf[j] >> 4) & 0xF;

                    ptr[j*2+1] = buf[j] & 0xF;

                }

                buf += n;

                ptr += linesize;

            }

            break;

        case 16:

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

                const uint16_t *src = (const uint16_t *) buf;

                uint16_t *dst       = (uint16_t *) ptr;

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

                    *dst++ = av_le2ne16(*src++);

                buf += n;

                ptr += linesize;

            }

            break;

        default:

            av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n");

            return AVERROR_INVALIDDATA;

        }

    }

    if (avctx->pix_fmt == AV_PIX_FMT_BGRA) {

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

            int j;

            uint8_t *ptr = p->data[0] + p->linesize[0]*i + 3;

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

                if (ptr[4*j])

                    break;

            }

            if (j < avctx->width)

                break;

        }

        if (i == avctx->height)

            avctx->pix_fmt = p->format = AV_PIX_FMT_BGR0;

    }

    *got_frame = 1;

    return buf_size;

}


static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,

                                                 uint32_t length)

{

    QIOChannel *ioc;

    QIOChannelTLS *tioc;

    struct NBDTLSHandshakeData data = { 0 };

    TRACE("Setting up TLS");

    ioc = client->ioc;

    if (length) {

        if (nbd_negotiate_drop_sync(ioc, length) != length) {

            return NULL;

        }

        nbd_negotiate_send_rep(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS);

        return NULL;

    }

    nbd_negotiate_send_rep(client->ioc, NBD_REP_ACK, NBD_OPT_STARTTLS);

    tioc = qio_channel_tls_new_server(ioc,

                                      client->tlscreds,

                                      client->tlsaclname,

                                      NULL);

    if (!tioc) {

        return NULL;

    }

    TRACE("Starting TLS handshake");

    data.loop = g_main_loop_new(g_main_context_default(), FALSE);

    qio_channel_tls_handshake(tioc,

                              nbd_tls_handshake,

                              &data,

                              NULL);

    if (!data.complete) {

        g_main_loop_run(data.loop);

    }

    g_main_loop_unref(data.loop);

    if (data.error) {

        object_unref(OBJECT(tioc));

        error_free(data.error);

        return NULL;

    }

    return QIO_CHANNEL(tioc);

}