static void do_video_out(AVFormatContext *s,

                         OutputStream *ost,

                         InputStream *ist,

                         AVFrame *in_picture,

                         int *frame_size, float quality)

{

    int nb_frames, i, ret, av_unused resample_changed;

    AVFrame *final_picture, *formatted_picture;

    AVCodecContext *enc, *dec;

    double sync_ipts;

    enc = ost->st->codec;

    dec = ist->st->codec;

    sync_ipts = get_sync_ipts(ost) / av_q2d(enc->time_base);

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

    nb_frames = 1;

    *frame_size = 0;

    if(video_sync_method){

        double vdelta = sync_ipts - ost->sync_opts;

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

        if (vdelta < -1.1)

            nb_frames = 0;

        else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){

            if(vdelta<=-0.6){

                nb_frames=0;

            }else if(vdelta>0.6)

                ost->sync_opts= lrintf(sync_ipts);

        }else if (vdelta > 1.1)

            nb_frames = lrintf(vdelta);

//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames);

        if (nb_frames == 0){

            ++nb_frames_drop;

            if (verbose>2)

                fprintf(stderr, "*** drop!\n");

        }else if (nb_frames > 1) {

            nb_frames_dup += nb_frames - 1;

            if (verbose>2)

                fprintf(stderr, "*** %d dup!\n", nb_frames-1);

        }

    }else

        ost->sync_opts= lrintf(sync_ipts);

    nb_frames= FFMIN(nb_frames, max_frames[AVMEDIA_TYPE_VIDEO] - ost->frame_number);

    if (nb_frames <= 0)

        return;

    formatted_picture = in_picture;

    final_picture = formatted_picture;

#if !CONFIG_AVFILTER

    resample_changed = ost->resample_width   != dec->width  ||

                       ost->resample_height  != dec->height ||

                       ost->resample_pix_fmt != dec->pix_fmt;

    if (resample_changed) {

        av_log(NULL, AV_LOG_INFO,

               "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",

               ist->file_index, ist->st->index,

               ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),

               dec->width         , dec->height         , av_get_pix_fmt_name(dec->pix_fmt));

        ost->resample_width   = dec->width;

        ost->resample_height  = dec->height;

        ost->resample_pix_fmt = dec->pix_fmt;

    }

    ost->video_resample = dec->width   != enc->width  ||

                          dec->height  != enc->height ||

                          dec->pix_fmt != enc->pix_fmt;

    if (ost->video_resample) {

        final_picture = &ost->resample_frame;

        if (!ost->img_resample_ctx || resample_changed) {

            /* initialize the destination picture */

            if (!ost->resample_frame.data[0]) {

                avcodec_get_frame_defaults(&ost->resample_frame);

                if (avpicture_alloc((AVPicture *)&ost->resample_frame, enc->pix_fmt,

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

                    fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n");

                    exit_program(1);

                }

            }

            /* initialize a new scaler context */

            sws_freeContext(ost->img_resample_ctx);

            ost->img_resample_ctx = sws_getContext(dec->width, dec->height, dec->pix_fmt,

                                                   enc->width, enc->height, enc->pix_fmt,

                                                   ost->sws_flags, NULL, NULL, NULL);

            if (ost->img_resample_ctx == NULL) {

                fprintf(stderr, "Cannot get resampling context\n");

                exit_program(1);

            }

        }

        sws_scale(ost->img_resample_ctx, formatted_picture->data, formatted_picture->linesize,

              0, ost->resample_height, final_picture->data, final_picture->linesize);

    }

#else

    if (resample_changed) {

        avfilter_graph_free(&ost->graph);

        if (configure_video_filters(ist, ost)) {

            fprintf(stderr, "Error reinitialising filters!\n");

            exit_program(1);

        }

    }

#endif

    if (resample_changed) {

        ost->resample_width   = dec->width;

        ost->resample_height  = dec->height;

        ost->resample_pix_fmt = dec->pix_fmt;

    }

    /* duplicates frame if needed */

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

        AVPacket pkt;

        av_init_packet(&pkt);

        pkt.stream_index= ost->index;

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

            /* raw pictures are written as AVPicture structure to

               avoid any copies. We support temorarily the older

               method. */

            AVFrame* old_frame = enc->coded_frame;

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

            pkt.data= (uint8_t *)final_picture;

            pkt.size=  sizeof(AVPicture);

            pkt.pts= av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base);

            pkt.flags |= AV_PKT_FLAG_KEY;

            write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters);

            enc->coded_frame = old_frame;

        } else {

            AVFrame big_picture;

            big_picture= *final_picture;

            /* better than nothing: use input picture interlaced

               settings */

            big_picture.interlaced_frame = in_picture->interlaced_frame;

            if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) {

                if(top_field_first == -1)

                    big_picture.top_field_first = in_picture->top_field_first;

                else

                    big_picture.top_field_first = top_field_first;

            }

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

               not be a global option */

            big_picture.quality = quality;

            if(!me_threshold)

                big_picture.pict_type = 0;

//            big_picture.pts = AV_NOPTS_VALUE;

            big_picture.pts= ost->sync_opts;

//            big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);

//av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);

            if (ost->forced_kf_index < ost->forced_kf_count &&

                big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) {

                big_picture.pict_type = AV_PICTURE_TYPE_I;

                ost->forced_kf_index++;

            }

            ret = avcodec_encode_video(enc,

                                       bit_buffer, bit_buffer_size,

                                       &big_picture);

            if (ret < 0) {

                fprintf(stderr, "Video encoding failed\n");

                exit_program(1);

            }

            if(ret>0){

                pkt.data= bit_buffer;

                pkt.size= ret;

                if(enc->coded_frame->pts != AV_NOPTS_VALUE)

                    pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);

/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n",

   pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1,

   pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/

                if(enc->coded_frame->key_frame)

                    pkt.flags |= AV_PKT_FLAG_KEY;

                write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters);

                *frame_size = ret;

                video_size += ret;

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

                //        enc->frame_number-1, ret, enc->pict_type);

                /* if two pass, output log */

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

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

                }

            }

        }

        ost->sync_opts++;

        ost->frame_number++;

    }

}


static void continue_after_map_failure(void *opaque)

{

    DMAAIOCB *dbs = (DMAAIOCB *)opaque;

    dbs->bh = qemu_bh_new(reschedule_dma, dbs);

    qemu_bh_schedule(dbs->bh);

}


static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)

{

    EHCIState *s = ptr;

    uint32_t *mmio = (uint32_t *)(&s->mmio[addr]);

    uint32_t old = *mmio;

    int i;

    trace_usb_ehci_mmio_writel(addr, addr2str(addr), val);

    /* Only aligned reads are allowed on OHCI */

    if (addr & 3) {

        fprintf(stderr, "usb-ehci: Mis-aligned write to addr 0x"

                TARGET_FMT_plx "\n", addr);

        return;

    }

    if (addr >= PORTSC && addr < PORTSC + 4 * NB_PORTS) {

        handle_port_status_write(s, (addr-PORTSC)/4, val);

        trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);

        return;

    }

    if (addr < OPREGBASE) {

        fprintf(stderr, "usb-ehci: write attempt to read-only register"

                TARGET_FMT_plx "\n", addr);

        return;

    }

    /* Do any register specific pre-write processing here.  */

    switch(addr) {

    case USBCMD:

        if (val & USBCMD_HCRESET) {

            ehci_reset(s);

            val = s->usbcmd;

            break;

        }

        if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=

            ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {

            if (!ehci_enabled(s)) {

                qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));

                SET_LAST_RUN_CLOCK(s);

            }

            ehci_update_halt(s);

        }

        /* not supporting dynamic frame list size at the moment */

        if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {

            fprintf(stderr, "attempt to set frame list size -- value %d\n",

                    val & USBCMD_FLS);

            val &= ~USBCMD_FLS;

        }

        break;

    case USBSTS:

        val &= USBSTS_RO_MASK;              // bits 6 through 31 are RO

        ehci_clear_usbsts(s, val);          // bits 0 through 5 are R/WC

        val = s->usbsts;

        ehci_set_interrupt(s, 0);

        break;

    case USBINTR:

        val &= USBINTR_MASK;

        break;

    case FRINDEX:

        val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */

        break;

    case CONFIGFLAG:

        val &= 0x1;

        if (val) {

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

                handle_port_owner_write(s, i, 0);

        }

        break;

    case PERIODICLISTBASE:

        if (ehci_periodic_enabled(s)) {

            fprintf(stderr,

              "ehci: PERIODIC list base register set while periodic schedule\n"

              "      is enabled and HC is enabled\n");

        }

        break;

    case ASYNCLISTADDR:

        if (ehci_async_enabled(s)) {

            fprintf(stderr,

              "ehci: ASYNC list address register set while async schedule\n"

              "      is enabled and HC is enabled\n");

        }

        break;

    }

    *mmio = val;

    trace_usb_ehci_mmio_change(addr, addr2str(addr), *mmio, old);

}


sPAPRDRConnector *spapr_drc_by_index(uint32_t index)

{

    Object *obj;

    char name[256];

    snprintf(name, sizeof(name), "%s/%x", DRC_CONTAINER_PATH, index);

    obj = object_resolve_path(name, NULL);

    return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);

}


uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)

{

    CPU_DoubleU farg1, farg2, farg3;

    farg1.ll = arg1;

    farg2.ll = arg2;

    farg3.ll = arg3;

    if (unlikely(float64_is_signaling_nan(farg1.d) ||

                 float64_is_signaling_nan(farg2.d) ||

                 float64_is_signaling_nan(farg3.d))) {

        /* sNaN operation */

        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);

    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||

                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {

        /* Multiplication of zero by infinity */

        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);

    } else {

#if USE_PRECISE_EMULATION

#ifdef FLOAT128

        /* This is the way the PowerPC specification defines it */

        float128 ft0_128, ft1_128;

        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);

        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);

        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);

        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&

                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {

            /* Magnitude subtraction of infinities */

            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);

        } else {

            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);

            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);

            farg1.d = float128_to_float64(ft0_128, &env->fp_status);

        }

#else

        /* This is OK on x86 hosts */

        farg1.d = (farg1.d * farg2.d) + farg3.d;

#endif

#else

        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);

        farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);

#endif

        if (likely(!float64_is_nan(farg1.d)))

            farg1.d = float64_chs(farg1.d);

    }

    return farg1.ll;

}


static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)

{

    const struct cow_header_v2 *cow_header = (const void *)buf;

    if (buf_size >= sizeof(struct cow_header_v2) &&

        be32_to_cpu(cow_header->magic) == COW_MAGIC &&

        be32_to_cpu(cow_header->version) == COW_VERSION)

        return 100;

    else

        return 0;

}


uint64_t ram_bytes_remaining(void)

{

    return ram_save_remaining() * TARGET_PAGE_SIZE;

}


static int decode_ics(AACContext * ac, SingleChannelElement * sce, GetBitContext * gb, int common_window, int scale_flag) {

    Pulse pulse;

    TemporalNoiseShaping * tns = &sce->tns;

    IndividualChannelStream * ics = &sce->ics;

    float * out = sce->coeffs;

    int global_gain, pulse_present = 0;

    /* This assignment is to silence a GCC warning about the variable being used

     * uninitialized when in fact it always is.

     */

    pulse.num_pulse = 0;

    global_gain = get_bits(gb, 8);

    if (!common_window && !scale_flag) {

        if (decode_ics_info(ac, ics, gb, 0) < 0)

            return -1;

    }

    if (decode_band_types(ac, sce->band_type, sce->band_type_run_end, gb, ics) < 0)

        return -1;

    if (decode_scalefactors(ac, sce->sf, gb, global_gain, ics, sce->band_type, sce->band_type_run_end) < 0)

        return -1;

    pulse_present = 0;

    if (!scale_flag) {

        if ((pulse_present = get_bits1(gb))) {

            if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {

                av_log(ac->avccontext, AV_LOG_ERROR, "Pulse tool not allowed in eight short sequence.\n");

                return -1;

            }

            decode_pulses(&pulse, gb, ics->swb_offset);

        }

        if ((tns->present = get_bits1(gb)) && decode_tns(ac, tns, gb, ics))

            return -1;

        if (get_bits1(gb)) {

            av_log_missing_feature(ac->avccontext, "SSR", 1);

            return -1;

        }

    }

    if (decode_spectrum_and_dequant(ac, out, gb, sce->sf, pulse_present, &pulse, ics, sce->band_type) < 0)

        return -1;

    return 0;

}


static ssize_t buffered_flush(QEMUFileBuffered *s)

{

    size_t offset = 0;

    ssize_t ret = 0;

    DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);

    while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {

        size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer);

        ret = migrate_fd_put_buffer(s->migration_state, s->buffer + offset,

                                    to_send);

        if (ret <= 0) {

            DPRINTF("error flushing data, %zd\n", ret);

            break;

        } else {

            DPRINTF("flushed %zd byte(s)\n", ret);

            offset += ret;

            s->bytes_xfer += ret;

        }

    }

    DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size);

    memmove(s->buffer, s->buffer + offset, s->buffer_size - offset);

    s->buffer_size -= offset;

    if (ret < 0) {

        return ret;

    }

    return offset;

}


void pci_qdev_register(PCIDeviceInfo *info)

{

    info->qdev.init = pci_qdev_init;

    info->qdev.bus_type = BUS_TYPE_PCI;

    qdev_register(&info->qdev);

}


static void vhost_net_stop_one(struct vhost_net *net,

                               VirtIODevice *dev)

{

    struct vhost_vring_file file = { .fd = -1 };

    if (!net->dev.started) {

        return;

    }

    if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {

        for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {

            const VhostOps *vhost_ops = net->dev.vhost_ops;

            int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND,

                                          &file);

            assert(r >= 0);

        }

    }

    if (net->nc->info->poll) {

        net->nc->info->poll(net->nc, true);

    }

    vhost_dev_stop(&net->dev, dev);

    vhost_dev_disable_notifiers(&net->dev, dev);

}


static int rtsp_read_header(AVFormatContext *s,

                            AVFormatParameters *ap)

{

    RTSPState *rt = s->priv_data;

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

    URLContext *rtsp_hd;

    int port, i, ret, err;

    RTSPHeader reply1, *reply = &reply1;

    unsigned char *content = NULL;

    AVStream *st;

    RTSPStream *rtsp_st;

    int protocol_mask;

    rtsp_abort_req = 0;

    /* extract hostname and port */

    url_split(NULL, 0,

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

    if (port < 0)

        port = RTSP_DEFAULT_PORT;

    /* open the tcp connexion */

    snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);

    if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)

        return AVERROR_IO;

    rt->rtsp_hd = rtsp_hd;

    rt->seq = 0;

    /* describe the stream */

    snprintf(cmd, sizeof(cmd),

             "DESCRIBE %s RTSP/1.0\r\n"

             "Accept: application/sdp\r\n",

             s->filename);

    rtsp_send_cmd(s, cmd, reply, &content);

    if (!content) {

        err = AVERROR_INVALIDDATA;

        goto fail;

    }

    if (reply->status_code != RTSP_STATUS_OK) {

        err = AVERROR_INVALIDDATA;

        goto fail;

    }

    /* now we got the SDP description, we parse it */

    ret = sdp_parse(s, (const char *)content);

    av_freep(&content);

    if (ret < 0) {

        err = AVERROR_INVALIDDATA;

        goto fail;

    }

    protocol_mask = rtsp_default_protocols;

    /* for each stream, make the setup request */

    /* XXX: we assume the same server is used for the control of each

       RTSP stream */

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

        char transport[2048];

        AVInputFormat *fmt;

        st = s->streams[i];

        rtsp_st = st->priv_data;

        /* compute available transports */

        transport[0] = '\0';

        /* RTP/UDP */

        if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) {

            char buf[256];

            int j;

            /* first try in specified port range */

            if (rtsp_rtp_port_min != 0) {

                for(j=rtsp_rtp_port_min;j<=rtsp_rtp_port_max;j++) {

                    snprintf(buf, sizeof(buf), "rtp://?localport=%d", j);

                    if (!av_open_input_file(&rtsp_st->ic, buf,

                                            &rtp_demux, 0, NULL))

                        goto rtp_opened;

                }

            }

            /* then try on any port */

            if (av_open_input_file(&rtsp_st->ic, "rtp://",

                                       &rtp_demux, 0, NULL) < 0) {

                    err = AVERROR_INVALIDDATA;

                    goto fail;

            }

        rtp_opened:

            port = rtp_get_local_port(url_fileno(&rtsp_st->ic->pb));

            if (transport[0] != '\0')

                pstrcat(transport, sizeof(transport), ",");

            snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,

                     "RTP/AVP/UDP;unicast;client_port=%d-%d",

                     port, port + 1);

        }

        /* RTP/TCP */

        if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {

            if (transport[0] != '\0')

                pstrcat(transport, sizeof(transport), ",");

            snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,

                     "RTP/AVP/TCP");

        }

        if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {

            if (transport[0] != '\0')

                pstrcat(transport, sizeof(transport), ",");

            snprintf(transport + strlen(transport),

                     sizeof(transport) - strlen(transport) - 1,

                     "RTP/AVP/UDP;multicast");

        }

        snprintf(cmd, sizeof(cmd),

                 "SETUP %s RTSP/1.0\r\n"

                 "Transport: %s\r\n",

                 rtsp_st->control_url, transport);

        rtsp_send_cmd(s, cmd, reply, NULL);

        if (reply->status_code != RTSP_STATUS_OK ||

            reply->nb_transports != 1) {

            err = AVERROR_INVALIDDATA;

            goto fail;

        }

        /* XXX: same protocol for all streams is required */

        if (i > 0) {

            if (reply->transports[0].protocol != rt->protocol) {

                err = AVERROR_INVALIDDATA;

                goto fail;

            }

        } else {

            rt->protocol = reply->transports[0].protocol;

        }

        /* close RTP connection if not choosen */

        if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP &&

            (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP))) {

            av_close_input_file(rtsp_st->ic);

            rtsp_st->ic = NULL;

        }

        switch(reply->transports[0].protocol) {

        case RTSP_PROTOCOL_RTP_TCP:

            fmt = &rtp_demux;

            if (av_open_input_file(&rtsp_st->ic, "null", fmt, 0, NULL) < 0) {

                err = AVERROR_INVALIDDATA;

                goto fail;

            }

            rtsp_st->interleaved_min = reply->transports[0].interleaved_min;

            rtsp_st->interleaved_max = reply->transports[0].interleaved_max;

            break;

        case RTSP_PROTOCOL_RTP_UDP:

            {

                char url[1024];

                /* XXX: also use address if specified */

                snprintf(url, sizeof(url), "rtp://%s:%d",

                         host, reply->transports[0].server_port_min);

                if (rtp_set_remote_url(url_fileno(&rtsp_st->ic->pb), url) < 0) {

                    err = AVERROR_INVALIDDATA;

                    goto fail;

                }

            }

            break;

        case RTSP_PROTOCOL_RTP_UDP_MULTICAST:

            {

                char url[1024];

                int ttl;

                fmt = &rtp_demux;

                ttl = reply->transports[0].ttl;

                if (!ttl)

                    ttl = 16;

                snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d",

                         host,

                         reply->transports[0].server_port_min,

                         ttl);

                if (av_open_input_file(&rtsp_st->ic, url, fmt, 0, NULL) < 0) {

                    err = AVERROR_INVALIDDATA;

                    goto fail;

                }

            }

            break;

        }

    }

    /* use callback if available to extend setup */

    if (ff_rtsp_callback) {

        if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id,

                             NULL, 0, rt->last_reply) < 0) {

            err = AVERROR_INVALIDDATA;

            goto fail;

        }

    }

    /* start playing */

    snprintf(cmd, sizeof(cmd),

             "PLAY %s RTSP/1.0\r\n"

             "Range: npt=0-\r\n",

             s->filename);

    rtsp_send_cmd(s, cmd, reply, NULL);

    if (reply->status_code != RTSP_STATUS_OK) {

        err = AVERROR_INVALIDDATA;

        goto fail;

    }

#if 0

    /* open TCP with bufferized input */

    if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {

        if (url_fdopen(&rt->rtsp_gb, rt->rtsp_hd) < 0) {

            err = AVERROR_NOMEM;

            goto fail;

        }

    }

#endif

    return 0;

 fail:

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

        st = s->streams[i];

        rtsp_st = st->priv_data;

        if (rtsp_st) {

            if (rtsp_st->ic)

                av_close_input_file(rtsp_st->ic);

        }

        av_free(rtsp_st);

    }

    av_freep(&content);

    url_close(rt->rtsp_hd);

    return err;

}


int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw,

                                int mmu_idx, int is_softmmu)

{

    target_ulong phys;

    int prot;

    /* XXX: implement mmu */

    phys = address;

    prot = PAGE_READ | PAGE_WRITE;

    return tlb_set_page(env, address & TARGET_PAGE_MASK,

                        phys & TARGET_PAGE_MASK, prot,

                        mmu_idx, is_softmmu);

}


static int inc_refcounts(BlockDriverState *bs,

                         BdrvCheckResult *res,

                         void **refcount_table,

                         int64_t *refcount_table_size,

                         int64_t offset, int64_t size)

{

    BDRVQcow2State *s = bs->opaque;

    uint64_t start, last, cluster_offset, k, refcount;

    int ret;

    if (size <= 0) {

        return 0;

    }

    start = start_of_cluster(s, offset);

    last = start_of_cluster(s, offset + size - 1);

    for(cluster_offset = start; cluster_offset <= last;

        cluster_offset += s->cluster_size) {

        k = cluster_offset >> s->cluster_bits;

        if (k >= *refcount_table_size) {

            ret = realloc_refcount_array(s, refcount_table,

                                         refcount_table_size, k + 1);

            if (ret < 0) {

                res->check_errors++;

                return ret;

            }

        }

        refcount = s->get_refcount(*refcount_table, k);

        if (refcount == s->refcount_max) {

            fprintf(stderr, "ERROR: overflow cluster offset=0x%" PRIx64

                    "\n", cluster_offset);

            fprintf(stderr, "Use qemu-img amend to increase the refcount entry "

                    "width or qemu-img convert to create a clean copy if the "

                    "image cannot be opened for writing\n");

            res->corruptions++;

            continue;

        }

        s->set_refcount(*refcount_table, k, refcount + 1);

    }

    return 0;

}


static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,

                             uint64_t value, unsigned size)

{

    GICState **backref = (GICState **)opaque;

    GICState *s = *backref;

    int id = (backref - s->backref);

    gic_cpu_write(s, id, addr, value);

}


void stq_be_phys(target_phys_addr_t addr, uint64_t val)

{

    val = cpu_to_be64(val);

    cpu_physical_memory_write(addr, &val, 8);

}


static int fb_initialise(struct XenDevice *xendev)

{

    struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev);

    struct xenfb_page *fb_page;

    int videoram;

    int rc;

    if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1)

	videoram = 0;

    rc = common_bind(&fb->c);

    if (rc != 0)

	return rc;

    fb_page = fb->c.page;

    rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U,

			    fb_page->width, fb_page->height, fb_page->depth,

			    fb_page->mem_length, 0, fb_page->line_length);

    if (rc != 0)

	return rc;

    rc = xenfb_map_fb(fb);

    if (rc != 0)

	return rc;

#if 0  /* handled in xen_init_display() for now */

    if (!fb->have_console) {

        fb->c.ds = graphic_console_init(xenfb_update,

                                        xenfb_invalidate,

                                        NULL,

                                        NULL,

                                        fb);

        fb->have_console = 1;

    }

#endif

    if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1)

	fb->feature_update = 0;

    if (fb->feature_update)

	xenstore_write_be_int(xendev, "request-update", 1);

    xen_pv_printf(xendev, 1, "feature-update=%d, videoram=%d\n",

		  fb->feature_update, videoram);

    return 0;

}


static void gen_exts(int ot, TCGv reg)

{

    switch(ot) {

    case OT_BYTE:

        tcg_gen_ext8s_tl(reg, reg);

        break;

    case OT_WORD:

        tcg_gen_ext16s_tl(reg, reg);

        break;

    case OT_LONG:

        tcg_gen_ext32s_tl(reg, reg);

        break;

    default:

        break;

    }

}


bool is_valid_option_list(const char *param)

{

    size_t buflen = strlen(param) + 1;

    char *buf = g_malloc(buflen);

    const char *p = param;

    bool result = true;

    while (*p) {

        p = get_opt_value(buf, buflen, p);

        if (*p && !*++p) {

            result = false;

            goto out;

        }

        if (!*buf || *buf == ',') {

            result = false;

            goto out;

        }

    }

out:

    free(buf);

    return result;

}


int ff_h264_alloc_tables(H264Context *h){

    MpegEncContext * const s = &h->s;

    const int big_mb_num= s->mb_stride * (s->mb_height+1);

    const int row_mb_num= 2*s->mb_stride*s->avctx->thread_count;

    int x,y;

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->intra4x4_pred_mode, row_mb_num * 8  * sizeof(uint8_t), fail)

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->non_zero_count    , big_mb_num * 48 * sizeof(uint8_t), fail)

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->slice_table_base  , (big_mb_num+s->mb_stride) * sizeof(*h->slice_table_base), fail)

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->cbp_table, big_mb_num * sizeof(uint16_t), fail)

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->chroma_pred_mode_table, big_mb_num * sizeof(uint8_t), fail)

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->mvd_table[0], 16*row_mb_num * sizeof(uint8_t), fail);

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->mvd_table[1], 16*row_mb_num * sizeof(uint8_t), fail);

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->direct_table, 4*big_mb_num * sizeof(uint8_t) , fail);

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->list_counts, big_mb_num * sizeof(uint8_t), fail)

    memset(h->slice_table_base, -1, (big_mb_num+s->mb_stride)  * sizeof(*h->slice_table_base));

    h->slice_table= h->slice_table_base + s->mb_stride*2 + 1;

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->mb2b_xy  , big_mb_num * sizeof(uint32_t), fail);

    FF_ALLOCZ_OR_GOTO(h->s.avctx, h->mb2br_xy , big_mb_num * sizeof(uint32_t), fail);

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

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

            const int mb_xy= x + y*s->mb_stride;

            const int b_xy = 4*x + 4*y*h->b_stride;

            h->mb2b_xy [mb_xy]= b_xy;

            h->mb2br_xy[mb_xy]= 8*(FMO ? mb_xy : (mb_xy % (2*s->mb_stride)));

        }

    }

    s->obmc_scratchpad = NULL;

    if(!h->dequant4_coeff[0])

        init_dequant_tables(h);

    return 0;

fail:

    free_tables(h, 1);

    return -1;

}


static inline CopyRet copy_frame(AVCodecContext *avctx,

                                 BC_DTS_PROC_OUT *output,

                                 void *data, int *data_size,

                                 uint8_t second_field)

{

    BC_STATUS ret;

    BC_DTS_STATUS decoder_status;

    uint8_t is_paff;

    uint8_t next_frame_same;

    uint8_t interlaced;

    CHDContext *priv = avctx->priv_data;

    uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==

                           VDEC_FLAG_BOTTOMFIELD;

    uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);

    int width    = output->PicInfo.width;

    int height   = output->PicInfo.height;

    int bwidth;

    uint8_t *src = output->Ybuff;

    int sStride;

    uint8_t *dst;

    int dStride;

    ret = DtsGetDriverStatus(priv->dev, &decoder_status);

    if (ret != BC_STS_SUCCESS) {

        av_log(avctx, AV_LOG_ERROR,

               "CrystalHD: GetDriverStatus failed: %u\n", ret);

       return RET_ERROR;

    }

    is_paff           = ASSUME_PAFF_OVER_MBAFF ||

                        !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC);

    next_frame_same   = output->PicInfo.picture_number ==

                        (decoder_status.picNumFlags & ~0x40000000);

    interlaced        = ((output->PicInfo.flags &

                          VDEC_FLAG_INTERLACED_SRC) && is_paff) ||

                         next_frame_same || bottom_field || second_field;

    av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: next_frame_same: %u | %u | %u\n",

           next_frame_same, output->PicInfo.picture_number,

           decoder_status.picNumFlags & ~0x40000000);

    if (priv->pic.data[0] && !priv->need_second_field)

        avctx->release_buffer(avctx, &priv->pic);

    priv->need_second_field = interlaced && !priv->need_second_field;

    priv->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |

                             FF_BUFFER_HINTS_REUSABLE;

    if (!priv->pic.data[0]) {

        if (avctx->get_buffer(avctx, &priv->pic) < 0) {

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

            return RET_ERROR;

        }

    }

    bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0);

    if (priv->is_70012) {

        int pStride;

        if (width <= 720)

            pStride = 720;

        else if (width <= 1280)

            pStride = 1280;

        else if (width <= 1080)

            pStride = 1080;

        sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);

    } else {

        sStride = bwidth;

    }

    dStride = priv->pic.linesize[0];

    dst     = priv->pic.data[0];

    av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");

    if (interlaced) {

        int dY = 0;

        int sY = 0;

        height /= 2;

        if (bottom_field) {

            av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");

            dY = 1;

        } else {

            av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");

            dY = 0;

        }

        for (sY = 0; sY < height; dY++, sY++) {

            memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);

            if (interlaced)

                dY++;

        }

    } else {

        av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);

    }

    priv->pic.interlaced_frame = interlaced;

    if (interlaced)

        priv->pic.top_field_first = !bottom_first;

    if (output->PicInfo.timeStamp != 0) {

        priv->pic.pkt_pts = opaque_list_pop(priv, output->PicInfo.timeStamp);

        av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n",

               priv->pic.pkt_pts);

    }

    if (!priv->need_second_field) {

        *data_size       = sizeof(AVFrame);

        *(AVFrame *)data = priv->pic;

    }

    if (ASSUME_TWO_INPUTS_ONE_OUTPUT &&

        output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) {

        av_log(priv->avctx, AV_LOG_VERBOSE, "Fieldpair from two packets.\n");

        return RET_SKIP_NEXT_COPY;

    }

    return RET_OK;

}


static void net_l2tpv3_cleanup(NetClientState *nc)

{

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

    qemu_purge_queued_packets(nc);

    l2tpv3_read_poll(s, false);

    l2tpv3_write_poll(s, false);

    if (s->fd > 0) {

        close(s->fd);

    }

    destroy_vector(s->msgvec, MAX_L2TPV3_MSGCNT, IOVSIZE);

    g_free(s->vec);

    g_free(s->header_buf);

    g_free(s->dgram_dst);

}


static AioHandler *find_aio_handler(int fd)

{

    AioHandler *node;

    LIST_FOREACH(node, &aio_handlers, node) {

        if (node->fd == fd)

            return node;

    }

    return NULL;

}


static inline void RENAME(yuv2yuv1)(SwsContext *c, const int16_t *lumSrc, const int16_t *chrSrc, const int16_t *alpSrc,

                                    uint8_t *dest, uint8_t *uDest, uint8_t *vDest, uint8_t *aDest, long dstW, long chrDstW)

{

    int i;

#if COMPILE_TEMPLATE_MMX

    if(!(c->flags & SWS_BITEXACT)) {

        long p= 4;

        const int16_t *src[4]= {alpSrc + dstW, lumSrc + dstW, chrSrc + chrDstW, chrSrc + VOFW + chrDstW};

        uint8_t *dst[4]= {aDest, dest, uDest, vDest};

        x86_reg counter[4]= {dstW, dstW, chrDstW, chrDstW};

        if (c->flags & SWS_ACCURATE_RND) {

            while(p--) {

                if (dst[p]) {

                    __asm__ volatile(

                        YSCALEYUV2YV121_ACCURATE

                        :: "r" (src[p]), "r" (dst[p] + counter[p]),

                        "g" (-counter[p])

                        : "%"REG_a

                    );

                }

            }

        } else {

            while(p--) {

                if (dst[p]) {

                    __asm__ volatile(

                        YSCALEYUV2YV121

                        :: "r" (src[p]), "r" (dst[p] + counter[p]),

                        "g" (-counter[p])

                        : "%"REG_a

                    );

                }

            }

        }

        return;

    }

#endif

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

        int val= (lumSrc[i]+64)>>7;

        if (val&256) {

            if (val<0) val=0;

            else       val=255;

        }

        dest[i]= val;

    }

    if (uDest)

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

            int u=(chrSrc[i       ]+64)>>7;

            int v=(chrSrc[i + VOFW]+64)>>7;

            if ((u|v)&256) {

                if (u<0)        u=0;

                else if (u>255) u=255;

                if (v<0)        v=0;

                else if (v>255) v=255;

            }

            uDest[i]= u;

            vDest[i]= v;

        }

    if (CONFIG_SWSCALE_ALPHA && aDest)

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

            int val= (alpSrc[i]+64)>>7;

            aDest[i]= av_clip_uint8(val);

        }

}


int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)

{

    X86CPU *cpu = X86_CPU(cs);

    CPUX86State *env = &cpu->env;

    uint32_t tmp;

    if (n < CPU_NB_REGS) {

        if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {

            env->regs[gpr_map[n]] = ldtul_p(mem_buf);

            return sizeof(target_ulong);

        } else if (n < CPU_NB_REGS32) {

            n = gpr_map32[n];

            env->regs[n] &= ~0xffffffffUL;

            env->regs[n] |= (uint32_t)ldl_p(mem_buf);

            return 4;

        }

    } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {

#ifdef USE_X86LDOUBLE

        /* FIXME: byteswap float values - after fixing fpregs layout. */

        memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10);

#endif

        return 10;

    } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {

        n -= IDX_XMM_REGS;

        if (n < CPU_NB_REGS32 ||

            (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {

            env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);

            env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);

            return 16;

        }

    } else {

        switch (n) {

        case IDX_IP_REG:

            if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {

                env->eip = ldq_p(mem_buf);

                return 8;

            } else {

                env->eip &= ~0xffffffffUL;

                env->eip |= (uint32_t)ldl_p(mem_buf);

                return 4;

            }

        case IDX_FLAGS_REG:

            env->eflags = ldl_p(mem_buf);

            return 4;

        case IDX_SEG_REGS:

            return x86_cpu_gdb_load_seg(cpu, R_CS, mem_buf);

        case IDX_SEG_REGS + 1:

            return x86_cpu_gdb_load_seg(cpu, R_SS, mem_buf);

        case IDX_SEG_REGS + 2:

            return x86_cpu_gdb_load_seg(cpu, R_DS, mem_buf);

        case IDX_SEG_REGS + 3:

            return x86_cpu_gdb_load_seg(cpu, R_ES, mem_buf);

        case IDX_SEG_REGS + 4:

            return x86_cpu_gdb_load_seg(cpu, R_FS, mem_buf);

        case IDX_SEG_REGS + 5:

            return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);

        case IDX_FP_REGS + 8:

            env->fpuc = ldl_p(mem_buf);

            return 4;

        case IDX_FP_REGS + 9:

            tmp = ldl_p(mem_buf);

            env->fpstt = (tmp >> 11) & 7;

            env->fpus = tmp & ~0x3800;

            return 4;

        case IDX_FP_REGS + 10: /* ftag */

            return 4;

        case IDX_FP_REGS + 11: /* fiseg */

            return 4;

        case IDX_FP_REGS + 12: /* fioff */

            return 4;

        case IDX_FP_REGS + 13: /* foseg */

            return 4;

        case IDX_FP_REGS + 14: /* fooff */

            return 4;

        case IDX_FP_REGS + 15: /* fop */

            return 4;

        case IDX_MXCSR_REG:

            env->mxcsr = ldl_p(mem_buf);

            return 4;

        }

    }

    /* Unrecognised register.  */

    return 0;

}


int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx,

                                     H264ParamSets *ps)

{

    AVBufferRef *sps_buf;

    int profile_idc, level_idc, constraint_set_flags = 0;

    unsigned int sps_id;

    int i, log2_max_frame_num_minus4;

    SPS *sps;

    profile_idc           = get_bits(gb, 8);

    constraint_set_flags |= get_bits1(gb) << 0;   // constraint_set0_flag

    constraint_set_flags |= get_bits1(gb) << 1;   // constraint_set1_flag

    constraint_set_flags |= get_bits1(gb) << 2;   // constraint_set2_flag

    constraint_set_flags |= get_bits1(gb) << 3;   // constraint_set3_flag

    constraint_set_flags |= get_bits1(gb) << 4;   // constraint_set4_flag

    constraint_set_flags |= get_bits1(gb) << 5;   // constraint_set5_flag

    skip_bits(gb, 2);                             // reserved_zero_2bits

    level_idc = get_bits(gb, 8);

    sps_id    = get_ue_golomb_31(gb);

    if (sps_id >= MAX_SPS_COUNT) {

        av_log(avctx, AV_LOG_ERROR, "sps_id %u out of range\n", sps_id);

        return AVERROR_INVALIDDATA;

    }

    sps_buf = av_buffer_allocz(sizeof(*sps));

    if (!sps_buf)

        return AVERROR(ENOMEM);

    sps = (SPS*)sps_buf->data;

    sps->sps_id               = sps_id;

    sps->time_offset_length   = 24;

    sps->profile_idc          = profile_idc;

    sps->constraint_set_flags = constraint_set_flags;

    sps->level_idc            = level_idc;

    memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4));

    memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8));

    sps->scaling_matrix_present = 0;

    if (sps->profile_idc == 100 ||  // High profile

        sps->profile_idc == 110 ||  // High10 profile

        sps->profile_idc == 122 ||  // High422 profile

        sps->profile_idc == 244 ||  // High444 Predictive profile

        sps->profile_idc ==  44 ||  // Cavlc444 profile

        sps->profile_idc ==  83 ||  // Scalable Constrained High profile (SVC)

        sps->profile_idc ==  86 ||  // Scalable High Intra profile (SVC)

        sps->profile_idc == 118 ||  // Stereo High profile (MVC)

        sps->profile_idc == 128 ||  // Multiview High profile (MVC)

        sps->profile_idc == 138 ||  // Multiview Depth High profile (MVCD)

        sps->profile_idc == 144) {  // old High444 profile

        sps->chroma_format_idc = get_ue_golomb_31(gb);

        if (sps->chroma_format_idc > 3) {

            avpriv_request_sample(avctx, "chroma_format_idc %u",

                                  sps->chroma_format_idc);

            goto fail;

        } else if (sps->chroma_format_idc == 3) {

            sps->residual_color_transform_flag = get_bits1(gb);

        }

        sps->bit_depth_luma   = get_ue_golomb(gb) + 8;

        sps->bit_depth_chroma = get_ue_golomb(gb) + 8;

        if (sps->bit_depth_chroma != sps->bit_depth_luma) {

            avpriv_request_sample(avctx,

                                  "Different chroma and luma bit depth");

            goto fail;

        }

        sps->transform_bypass = get_bits1(gb);

        decode_scaling_matrices(gb, sps, NULL, 1,

                                sps->scaling_matrix4, sps->scaling_matrix8);

    } else {

        sps->chroma_format_idc = 1;

        sps->bit_depth_luma    = 8;

        sps->bit_depth_chroma  = 8;

    }

    log2_max_frame_num_minus4 = get_ue_golomb(gb);

    if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 ||

        log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) {

        av_log(avctx, AV_LOG_ERROR,

               "log2_max_frame_num_minus4 out of range (0-12): %d\n",

               log2_max_frame_num_minus4);

        goto fail;

    }

    sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4;

    sps->poc_type = get_ue_golomb_31(gb);

    if (sps->poc_type == 0) { // FIXME #define

        sps->log2_max_poc_lsb = get_ue_golomb(gb) + 4;

    } else if (sps->poc_type == 1) { // FIXME #define

        sps->delta_pic_order_always_zero_flag = get_bits1(gb);

        sps->offset_for_non_ref_pic           = get_se_golomb(gb);

        sps->offset_for_top_to_bottom_field   = get_se_golomb(gb);

        sps->poc_cycle_length                 = get_ue_golomb(gb);

        if ((unsigned)sps->poc_cycle_length >=

            FF_ARRAY_ELEMS(sps->offset_for_ref_frame)) {

            av_log(avctx, AV_LOG_ERROR,

                   "poc_cycle_length overflow %d\n", sps->poc_cycle_length);

            goto fail;

        }

        for (i = 0; i < sps->poc_cycle_length; i++)

            sps->offset_for_ref_frame[i] = get_se_golomb(gb);

    } else if (sps->poc_type != 2) {

        av_log(avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type);

        goto fail;

    }

    sps->ref_frame_count = get_ue_golomb_31(gb);

    if (sps->ref_frame_count > H264_MAX_PICTURE_COUNT - 2 ||

        sps->ref_frame_count >= 32U) {

        av_log(avctx, AV_LOG_ERROR,

               "too many reference frames %d\n", sps->ref_frame_count);

        goto fail;

    }

    sps->gaps_in_frame_num_allowed_flag = get_bits1(gb);

    sps->mb_width                       = get_ue_golomb(gb) + 1;

    sps->mb_height                      = get_ue_golomb(gb) + 1;

    if ((unsigned)sps->mb_width  >= INT_MAX / 16 ||

        (unsigned)sps->mb_height >= INT_MAX / 16 ||

        av_image_check_size(16 * sps->mb_width,

                            16 * sps->mb_height, 0, avctx)) {

        av_log(avctx, AV_LOG_ERROR, "mb_width/height overflow\n");

        goto fail;

    }

    sps->frame_mbs_only_flag = get_bits1(gb);

    if (!sps->frame_mbs_only_flag)

        sps->mb_aff = get_bits1(gb);

    else

        sps->mb_aff = 0;

    sps->direct_8x8_inference_flag = get_bits1(gb);

    if (!sps->frame_mbs_only_flag && !sps->direct_8x8_inference_flag) {

        av_log(avctx, AV_LOG_ERROR,

               "This stream was generated by a broken encoder, invalid 8x8 inference\n");

        goto fail;

    }

#ifndef ALLOW_INTERLACE

    if (sps->mb_aff)

        av_log(avctx, AV_LOG_ERROR,

               "MBAFF support not included; enable it at compile-time.\n");

#endif

    sps->crop = get_bits1(gb);

    if (sps->crop) {

        unsigned int crop_left   = get_ue_golomb(gb);

        unsigned int crop_right  = get_ue_golomb(gb);

        unsigned int crop_top    = get_ue_golomb(gb);

        unsigned int crop_bottom = get_ue_golomb(gb);

        if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) {

            av_log(avctx, AV_LOG_DEBUG, "discarding sps cropping, original "

                                           "values are l:%d r:%d t:%d b:%d\n",

                   crop_left, crop_right, crop_top, crop_bottom);

            sps->crop_left   =

            sps->crop_right  =

            sps->crop_top    =

            sps->crop_bottom = 0;

        } else {

            int vsub   = (sps->chroma_format_idc == 1) ? 1 : 0;

            int hsub   = (sps->chroma_format_idc == 1 ||

                          sps->chroma_format_idc == 2) ? 1 : 0;

            int step_x = 1 << hsub;

            int step_y = (2 - sps->frame_mbs_only_flag) << vsub;

            if (crop_left & (0x1F >> (sps->bit_depth_luma > 8)) &&

                !(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) {

                crop_left &= ~(0x1F >> (sps->bit_depth_luma > 8));

                av_log(avctx, AV_LOG_WARNING,

                       "Reducing left cropping to %d "

                       "chroma samples to preserve alignment.\n",

                       crop_left);

            }

            if (INT_MAX / step_x             <= crop_left               ||

                INT_MAX / step_x - crop_left <= crop_right              ||

                16 * sps->mb_width <= step_x * (crop_left + crop_right) ||

                INT_MAX / step_y             <= crop_top                ||

                INT_MAX / step_y - crop_top  <= crop_bottom             ||

                16 * sps->mb_height <= step_y * (crop_top + crop_bottom)) {

                av_log(avctx, AV_LOG_WARNING, "Invalid crop parameters\n");

                if (avctx->err_recognition & AV_EF_EXPLODE)

                    goto fail;

                crop_left = crop_right = crop_top = crop_bottom = 0;

            }

            sps->crop_left   = crop_left   * step_x;

            sps->crop_right  = crop_right  * step_x;

            sps->crop_top    = crop_top    * step_y;

            sps->crop_bottom = crop_bottom * step_y;

        }

    } else {

        sps->crop_left   =

        sps->crop_right  =

        sps->crop_top    =

        sps->crop_bottom =

        sps->crop        = 0;

    }

    sps->vui_parameters_present_flag = get_bits1(gb);

    if (sps->vui_parameters_present_flag) {

        int ret = decode_vui_parameters(gb, avctx, sps);

        if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE)

            goto fail;

    }

    /* if the maximum delay is not stored in the SPS, derive it based on the

     * level */

    if (!sps->bitstream_restriction_flag &&

        (sps->ref_frame_count || avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT)) {

        sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1;

        for (i = 0; i < FF_ARRAY_ELEMS(level_max_dpb_mbs); i++) {

            if (level_max_dpb_mbs[i][0] == sps->level_idc) {

                sps->num_reorder_frames = FFMIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height),

                                                sps->num_reorder_frames);

                break;

            }

        }

    }

    if (!sps->sar.den)

        sps->sar.den = 1;

    if (avctx->debug & FF_DEBUG_PICT_INFO) {

        static const char csp[4][5] = { "Gray", "420", "422", "444" };

        av_log(avctx, AV_LOG_DEBUG,

               "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%u/%u/%u/%u %s %s %"PRId32"/%"PRId32"\n",

               sps_id, sps->profile_idc, sps->level_idc,

               sps->poc_type,

               sps->ref_frame_count,

               sps->mb_width, sps->mb_height,

               sps->frame_mbs_only_flag ? "FRM" : (sps->mb_aff ? "MB-AFF" : "PIC-AFF"),

               sps->direct_8x8_inference_flag ? "8B8" : "",

               sps->crop_left, sps->crop_right,

               sps->crop_top, sps->crop_bottom,

               sps->vui_parameters_present_flag ? "VUI" : "",

               csp[sps->chroma_format_idc],

               sps->timing_info_present_flag ? sps->num_units_in_tick : 0,

               sps->timing_info_present_flag ? sps->time_scale : 0);

    }

    /* check if this is a repeat of an already parsed SPS, then keep the

     * original one.

     * otherwise drop all PPSes that depend on it */

    if (ps->sps_list[sps_id] &&

        !memcmp(ps->sps_list[sps_id]->data, sps_buf->data, sps_buf->size)) {

        av_buffer_unref(&sps_buf);

    } else {

        remove_sps(ps, sps_id);

        ps->sps_list[sps_id] = sps_buf;

    }

    return 0;

fail:

    av_buffer_unref(&sps_buf);

    return AVERROR_INVALIDDATA;

}


static void cchip_write(void *opaque, hwaddr addr,

                        uint64_t val, unsigned size)

{

    TyphoonState *s = opaque;

    uint64_t oldval, newval;

    switch (addr) {

    case 0x0000:

        /* CSC: Cchip System Configuration Register.  */

        /* All sorts of data here; nothing relevant RW.  */

        break;

    case 0x0040:

        /* MTR: Memory Timing Register.  */

        /* All sorts of stuff related to real DRAM.  */

        break;

    case 0x0080:

        /* MISC: Miscellaneous Register.  */

        newval = oldval = s->cchip.misc;

        newval &= ~(val & 0x10000ff0);     /* W1C fields */

        if (val & 0x100000) {

            newval &= ~0xff0000ull;        /* ACL clears ABT and ABW */

        } else {

            newval |= val & 0x00f00000;    /* ABT field is W1S */

            if ((newval & 0xf0000) == 0) {

                newval |= val & 0xf0000;   /* ABW field is W1S iff zero */

            }

        }

        newval |= (val & 0xf000) >> 4;     /* IPREQ field sets IPINTR.  */

        newval &= ~0xf0000000000ull;       /* WO and RW fields */

        newval |= val & 0xf0000000000ull;

        s->cchip.misc = newval;

        /* Pass on changes to IPI and ITI state.  */

        if ((newval ^ oldval) & 0xff0) {

            int i;

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

                AlphaCPU *cpu = s->cchip.cpu[i];

                if (cpu != NULL) {

                    CPUState *cs = CPU(cpu);

                    /* IPI can be either cleared or set by the write.  */

                    if (newval & (1 << (i + 8))) {

                        cpu_interrupt(cs, CPU_INTERRUPT_SMP);

                    } else {

                        cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);

                    }

                    /* ITI can only be cleared by the write.  */

                    if ((newval & (1 << (i + 4))) == 0) {

                        cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);

                    }

                }

            }

        }

        break;

    case 0x00c0:

        /* MPD: Memory Presence Detect Register.  */

        break;

    case 0x0100: /* AAR0 */

    case 0x0140: /* AAR1 */

    case 0x0180: /* AAR2 */

    case 0x01c0: /* AAR3 */

        /* AAR: Array Address Register.  */

        /* All sorts of information about DRAM.  */

        break;

    case 0x0200: /* DIM0 */

        /* DIM: Device Interrupt Mask Register, CPU0.  */

        s->cchip.dim[0] = val;

        cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);

        break;

    case 0x0240: /* DIM1 */

        /* DIM: Device Interrupt Mask Register, CPU1.  */

        s->cchip.dim[0] = val;

        cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);

        break;

    case 0x0280: /* DIR0 (RO) */

    case 0x02c0: /* DIR1 (RO) */

    case 0x0300: /* DRIR (RO) */

        break;

    case 0x0340:

        /* PRBEN: Probe Enable Register.  */

        break;

    case 0x0380: /* IIC0 */

        s->cchip.iic[0] = val & 0xffffff;

        break;

    case 0x03c0: /* IIC1 */

        s->cchip.iic[1] = val & 0xffffff;

        break;

    case 0x0400: /* MPR0 */

    case 0x0440: /* MPR1 */

    case 0x0480: /* MPR2 */

    case 0x04c0: /* MPR3 */

        /* MPR: Memory Programming Register.  */

        break;

    case 0x0580:

        /* TTR: TIGbus Timing Register.  */

        /* All sorts of stuff related to interrupt delivery timings.  */

        break;

    case 0x05c0:

        /* TDR: TIGbug Device Timing Register.  */

        break;

    case 0x0600:

        /* DIM2: Device Interrupt Mask Register, CPU2.  */

        s->cchip.dim[2] = val;

        cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);

        break;

    case 0x0640:

        /* DIM3: Device Interrupt Mask Register, CPU3.  */

        s->cchip.dim[3] = val;

        cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);

        break;

    case 0x0680: /* DIR2 (RO) */

    case 0x06c0: /* DIR3 (RO) */

        break;

    case 0x0700: /* IIC2 */

        s->cchip.iic[2] = val & 0xffffff;

        break;

    case 0x0740: /* IIC3 */

        s->cchip.iic[3] = val & 0xffffff;

        break;

    case 0x0780:

        /* PWR: Power Management Control.   */

        break;

    case 0x0c00: /* CMONCTLA */

    case 0x0c40: /* CMONCTLB */

    case 0x0c80: /* CMONCNT01 */

    case 0x0cc0: /* CMONCNT23 */

        break;

    default:

        cpu_unassigned_access(current_cpu, addr, true, false, 0, size);

        return;

    }

}


static void exynos4210_combiner_write(void *opaque, target_phys_addr_t offset,

        uint64_t val, unsigned size)

{

    struct Exynos4210CombinerState *s =

            (struct Exynos4210CombinerState *)opaque;

    uint32_t req_quad_base_n;    /* Base of registers quad. Multiply it by 4 and

                                   get a start of corresponding group quad */

    uint32_t grp_quad_base_n;    /* Base of group quad */

    uint32_t reg_n;              /* Register number inside the quad */

    req_quad_base_n = offset >> 4;

    grp_quad_base_n = req_quad_base_n << 2;

    reg_n = (offset - (req_quad_base_n << 4)) >> 2;

    if (req_quad_base_n >= IIC_NGRP) {

        hw_error("exynos4210.combiner: unallowed write access at offset 0x"

                TARGET_FMT_plx "\n", offset);

        return;

    }

    if (reg_n > 1) {

        hw_error("exynos4210.combiner: unallowed write access at offset 0x"

                TARGET_FMT_plx "\n", offset);

        return;

    }

    if (offset >> 2 >= IIC_REGSET_SIZE) {

        hw_error("exynos4210.combiner: overflow of reg_set by 0x"

                TARGET_FMT_plx "offset\n", offset);

    }

    s->reg_set[offset >> 2] = val;

    switch (reg_n) {

    /* IIESR */

    case 0:

        /* FIXME: what if irq is pending, allowed by mask, and we allow it

         * again. Interrupt will rise again! */

        DPRINTF("%s enable IRQ for groups %d, %d, %d, %d\n",

                s->external ? "EXT" : "INT",

                grp_quad_base_n,

                grp_quad_base_n + 1,

                grp_quad_base_n + 2,

                grp_quad_base_n + 3);

        /* Enable interrupt sources */

        s->group[grp_quad_base_n].src_mask |= val & 0xFF;

        s->group[grp_quad_base_n + 1].src_mask |= (val & 0xFF00) >> 8;

        s->group[grp_quad_base_n + 2].src_mask |= (val & 0xFF0000) >> 16;

        s->group[grp_quad_base_n + 3].src_mask |= (val & 0xFF000000) >> 24;

        exynos4210_combiner_update(s, grp_quad_base_n);

        exynos4210_combiner_update(s, grp_quad_base_n + 1);

        exynos4210_combiner_update(s, grp_quad_base_n + 2);

        exynos4210_combiner_update(s, grp_quad_base_n + 3);

        break;

        /* IIECR */

    case 1:

        DPRINTF("%s disable IRQ for groups %d, %d, %d, %d\n",

                s->external ? "EXT" : "INT",

                grp_quad_base_n,

                grp_quad_base_n + 1,

                grp_quad_base_n + 2,

                grp_quad_base_n + 3);

        /* Disable interrupt sources */

        s->group[grp_quad_base_n].src_mask &= ~(val & 0xFF);

        s->group[grp_quad_base_n + 1].src_mask &= ~((val & 0xFF00) >> 8);

        s->group[grp_quad_base_n + 2].src_mask &= ~((val & 0xFF0000) >> 16);

        s->group[grp_quad_base_n + 3].src_mask &= ~((val & 0xFF000000) >> 24);

        exynos4210_combiner_update(s, grp_quad_base_n);

        exynos4210_combiner_update(s, grp_quad_base_n + 1);

        exynos4210_combiner_update(s, grp_quad_base_n + 2);

        exynos4210_combiner_update(s, grp_quad_base_n + 3);

        break;

    default:

        hw_error("exynos4210.combiner: unallowed write access at offset 0x"

                TARGET_FMT_plx "\n", offset);

        break;

    }

}


static void bt_submit_acl(struct HCIInfo *info,

                const uint8_t *data, int length)

{

    struct bt_hci_s *hci = hci_from_info(info);

    uint16_t handle;

    int datalen, flags;

    struct bt_link_s *link;

    if (length < HCI_ACL_HDR_SIZE) {

        fprintf(stderr, "%s: ACL packet too short (%iB)\n",

                        __FUNCTION__, length);

        return;

    }

    handle = acl_handle((data[1] << 8) | data[0]);

    flags = acl_flags((data[1] << 8) | data[0]);

    datalen = (data[3] << 8) | data[2];

    data += HCI_ACL_HDR_SIZE;

    length -= HCI_ACL_HDR_SIZE;

    if (bt_hci_handle_bad(hci, handle)) {

        fprintf(stderr, "%s: invalid ACL handle %03x\n",

                        __FUNCTION__, handle);

        /* TODO: signal an error */

        return;

    }

    handle &= ~HCI_HANDLE_OFFSET;

    if (datalen > length) {

        fprintf(stderr, "%s: ACL packet too short (%iB < %iB)\n",

                        __FUNCTION__, length, datalen);

        return;

    }

    link = hci->lm.handle[handle].link;

    if ((flags & ~3) == ACL_ACTIVE_BCAST) {

        if (!hci->asb_handle)

            hci->asb_handle = handle;

        else if (handle != hci->asb_handle) {

            fprintf(stderr, "%s: Bad handle %03x in Active Slave Broadcast\n",

                            __FUNCTION__, handle);

            /* TODO: signal an error */

            return;

        }

        /* TODO */

    }

    if ((flags & ~3) == ACL_PICO_BCAST) {

        if (!hci->psb_handle)

            hci->psb_handle = handle;

        else if (handle != hci->psb_handle) {

            fprintf(stderr, "%s: Bad handle %03x in Parked Slave Broadcast\n",

                            __FUNCTION__, handle);

            /* TODO: signal an error */

            return;

        }

        /* TODO */

    }

    /* TODO: increase counter and send EVT_NUM_COMP_PKTS */

    bt_hci_event_num_comp_pkts(hci, handle | HCI_HANDLE_OFFSET, 1);

    /* Do this last as it can trigger further events even in this HCI */

    hci->lm.handle[handle].lmp_acl_data(link, data,

                    (flags & 3) == ACL_START, length);

}


static int nbd_co_flush(BlockDriverState *bs)

{

    BDRVNBDState *s = bs->opaque;

    return nbd_client_session_co_flush(&s->client);

}


static int qiov_is_aligned(QEMUIOVector *qiov)

{

    int i;

    for (i = 0; i < qiov->niov; i++) {

        if ((uintptr_t) qiov->iov[i].iov_base % BDRV_SECTOR_SIZE) {

            return 0;

        }

    }

    return 1;

}


static int seqvideo_decode_frame(AVCodecContext *avctx,

                                 void *data, int *data_size,

                                 AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data;

    int buf_size = avpkt->size;

    SeqVideoContext *seq = avctx->priv_data;

    seq->frame.reference = 1;

    seq->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;

    if (avctx->reget_buffer(avctx, &seq->frame)) {

        av_log(seq->avctx, AV_LOG_ERROR, "tiertexseqvideo: reget_buffer() failed\n");

        return -1;

    }

    seqvideo_decode(seq, buf, buf_size);

    *data_size = sizeof(AVFrame);

    *(AVFrame *)data = seq->frame;

    return buf_size;

}


static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,

                               size_t len)

{

    IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));

    IMXFECBufDesc bd;

    uint32_t flags = 0;

    uint32_t addr;

    uint32_t crc;

    uint32_t buf_addr;

    uint8_t *crc_ptr;

    unsigned int buf_len;

    size_t size = len;

    FEC_PRINTF("len %d\n", (int)size);

    if (!s->regs[ENET_RDAR]) {

        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n",

                      TYPE_IMX_FEC, __func__);

        return 0;

    }

    /* 4 bytes for the CRC.  */

    size += 4;

    crc = cpu_to_be32(crc32(~0, buf, size));

    crc_ptr = (uint8_t *) &crc;

    /* Huge frames are truncated.  */

    if (size > ENET_MAX_FRAME_SIZE) {

        size = ENET_MAX_FRAME_SIZE;

        flags |= ENET_BD_TR | ENET_BD_LG;

    }

    /* Frames larger than the user limit just set error flags.  */

    if (size > (s->regs[ENET_RCR] >> 16)) {

        flags |= ENET_BD_LG;

    }

    addr = s->rx_descriptor;

    while (size > 0) {

        imx_fec_read_bd(&bd, addr);

        if ((bd.flags & ENET_BD_E) == 0) {

            /* No descriptors available.  Bail out.  */

            /*

             * FIXME: This is wrong. We should probably either

             * save the remainder for when more RX buffers are

             * available, or flag an error.

             */

            qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Lost end of frame\n",

                          TYPE_IMX_FEC, __func__);

            break;

        }

        buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR];

        bd.length = buf_len;

        size -= buf_len;

        FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length);

        /* The last 4 bytes are the CRC.  */

        if (size < 4) {

            buf_len += size - 4;

        }

        buf_addr = bd.data;

        dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);

        buf += buf_len;

        if (size < 4) {

            dma_memory_write(&address_space_memory, buf_addr + buf_len,

                             crc_ptr, 4 - size);

            crc_ptr += 4 - size;

        }

        bd.flags &= ~ENET_BD_E;

        if (size == 0) {

            /* Last buffer in frame.  */

            bd.flags |= flags | ENET_BD_L;

            FEC_PRINTF("rx frame flags %04x\n", bd.flags);

            s->regs[ENET_EIR] |= ENET_INT_RXF;

        } else {

            s->regs[ENET_EIR] |= ENET_INT_RXB;

        }

        imx_fec_write_bd(&bd, addr);

        /* Advance to the next descriptor.  */

        if ((bd.flags & ENET_BD_W) != 0) {

            addr = s->regs[ENET_RDSR];

        } else {

            addr += sizeof(bd);

        }

    }

    s->rx_descriptor = addr;

    imx_eth_enable_rx(s);

    imx_eth_update(s);

    return len;

}


static void breakpoint_handler(CPUState *env)

{

    CPUBreakpoint *bp;

    if (env->watchpoint_hit) {

        if (env->watchpoint_hit->flags & BP_CPU) {

            env->watchpoint_hit = NULL;

            if (check_hw_breakpoints(env, 0))

                raise_exception(EXCP01_DB);

            else

                cpu_resume_from_signal(env, NULL);

        }

    } else {

        TAILQ_FOREACH(bp, &env->breakpoints, entry)

            if (bp->pc == env->eip) {

                if (bp->flags & BP_CPU) {

                    check_hw_breakpoints(env, 1);

                    raise_exception(EXCP01_DB);

                }

                break;

            }

    }

    if (prev_debug_excp_handler)

        prev_debug_excp_handler(env);

}


static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,

                                void *opaque)

{

    VirtualConsole *vc = opaque;

    GtkDisplayState *s = vc->s;

    InputButton btn;

    /* implicitly grab the input at the first click in the relative mode */

    if (button->button == 1 && button->type == GDK_BUTTON_PRESS &&

        !qemu_input_is_absolute() && !gd_is_grab_active(s)) {

        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),

                                       TRUE);

        return TRUE;

    }

    if (button->button == 1) {

        btn = INPUT_BUTTON_LEFT;

    } else if (button->button == 2) {

        btn = INPUT_BUTTON_MIDDLE;

    } else if (button->button == 3) {

        btn = INPUT_BUTTON_RIGHT;

    } else {

        return TRUE;

    }

    qemu_input_queue_btn(vc->gfx.dcl.con, btn,

                         button->type == GDK_BUTTON_PRESS);

    qemu_input_event_sync();

    return TRUE;

}


static void * attribute_align_arg worker(void *v){

    AVCodecContext *avctx = v;

    ThreadContext *c = avctx->internal->frame_thread_encoder;

    AVPacket *pkt = NULL;

    while(!c->exit){

        int got_packet, ret;

        AVFrame *frame;

        Task task;

        if(!pkt) pkt= av_mallocz(sizeof(*pkt));

        if(!pkt) continue;

        av_init_packet(pkt);

        pthread_mutex_lock(&c->task_fifo_mutex);

        while (av_fifo_size(c->task_fifo) <= 0 || c->exit) {

            if(c->exit){

                pthread_mutex_unlock(&c->task_fifo_mutex);

                goto end;

            }

            pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex);

        }

        av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL);

        pthread_mutex_unlock(&c->task_fifo_mutex);

        frame = task.indata;

        ret = avcodec_encode_video2(avctx, pkt, frame, &got_packet);

        pthread_mutex_lock(&c->buffer_mutex);

        av_frame_unref(frame);

        pthread_mutex_unlock(&c->buffer_mutex);

        av_frame_free(&frame);

        if(got_packet) {

            int ret2 = av_dup_packet(pkt);

            if (ret >= 0 && ret2 < 0)

                ret = ret2;

        } else {

            pkt->data = NULL;

            pkt->size = 0;

        }

        pthread_mutex_lock(&c->finished_task_mutex);

        c->finished_tasks[task.index].outdata = pkt; pkt = NULL;

        c->finished_tasks[task.index].return_code = ret;

        pthread_cond_signal(&c->finished_task_cond);

        pthread_mutex_unlock(&c->finished_task_mutex);

    }

end:

    av_free(pkt);

    pthread_mutex_lock(&c->buffer_mutex);

    avcodec_close(avctx);

    pthread_mutex_unlock(&c->buffer_mutex);

    av_freep(&avctx);

    return NULL;

}