static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,

                           int i, AVIOContext *pb, int default_stream_exists)

{

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

    AVCodecContext *codec = st->codec;

    ebml_master subinfo, track;

    int native_id = 0;

    int qt_id = 0;

    int bit_depth = av_get_bits_per_sample(codec->codec_id);

    int sample_rate = codec->sample_rate;

    int output_sample_rate = 0;

    int display_width_div = 1;

    int display_height_div = 1;

    int j, ret;

    AVDictionaryEntry *tag;

    // ms precision is the de-facto standard timescale for mkv files

    avpriv_set_pts_info(st, 64, 1, 1000);

    if (codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) {

        mkv->have_attachments = 1;

        return 0;

    }

    if (!bit_depth && codec->codec_id != AV_CODEC_ID_ADPCM_G726)

        bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3;

    if (!bit_depth)

        bit_depth = codec->bits_per_coded_sample;

    if (codec->codec_id == AV_CODEC_ID_AAC)

        get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate);

    track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);

    put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER,

                   mkv->is_dash ? mkv->dash_track_number : i + 1);

    put_ebml_uint (pb, MATROSKA_ID_TRACKUID,

                   mkv->is_dash ? mkv->dash_track_number : i + 1);

    put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0);    // no lacing (yet)

    if ((tag = av_dict_get(st->metadata, "title", NULL, 0)))

        put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value);

    tag = av_dict_get(st->metadata, "language", NULL, 0);

    if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) {

        put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag && tag->value ? tag->value:"und");

    } else if (tag && tag->value) {

        put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag->value);

    }

    // The default value for TRACKFLAGDEFAULT is 1, so add element

    // if we need to clear it.

    if (default_stream_exists && !(st->disposition & AV_DISPOSITION_DEFAULT))

        put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition & AV_DISPOSITION_DEFAULT));

    if (st->disposition & AV_DISPOSITION_FORCED)

        put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1);

    if (mkv->mode == MODE_WEBM && codec->codec_id == AV_CODEC_ID_WEBVTT) {

        const char *codec_id;

        if (st->disposition & AV_DISPOSITION_CAPTIONS) {

            codec_id = "D_WEBVTT/CAPTIONS";

            native_id = MATROSKA_TRACK_TYPE_SUBTITLE;

        } else if (st->disposition & AV_DISPOSITION_DESCRIPTIONS) {

            codec_id = "D_WEBVTT/DESCRIPTIONS";

            native_id = MATROSKA_TRACK_TYPE_METADATA;

        } else if (st->disposition & AV_DISPOSITION_METADATA) {

            codec_id = "D_WEBVTT/METADATA";

            native_id = MATROSKA_TRACK_TYPE_METADATA;

        } else {

            codec_id = "D_WEBVTT/SUBTITLES";

            native_id = MATROSKA_TRACK_TYPE_SUBTITLE;

        }

        put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id);

    } else {

        // look for a codec ID string specific to mkv to use,

        // if none are found, use AVI codes

        for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) {

            if (ff_mkv_codec_tags[j].id == codec->codec_id) {

                put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str);

                native_id = 1;

                break;

            }

        }

    }

    if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->delay && codec->codec_id == AV_CODEC_ID_OPUS) {

//         mkv->tracks[i].ts_offset = av_rescale_q(codec->delay,

//                                                 (AVRational){ 1, codec->sample_rate },

//                                                 st->time_base);

        put_ebml_uint(pb, MATROSKA_ID_CODECDELAY,

                      av_rescale_q(codec->delay, (AVRational){ 1, codec->sample_rate },

                                   (AVRational){ 1, 1000000000 }));

    }

    if (codec->codec_id == AV_CODEC_ID_OPUS) {

        put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL);

    }

    if (mkv->mode == MODE_WEBM && !(codec->codec_id == AV_CODEC_ID_VP8 ||

                                    codec->codec_id == AV_CODEC_ID_VP9 ||

                                    codec->codec_id == AV_CODEC_ID_OPUS ||

                                    codec->codec_id == AV_CODEC_ID_VORBIS ||

                                    codec->codec_id == AV_CODEC_ID_WEBVTT)) {

        av_log(s, AV_LOG_ERROR,

               "Only VP8 or VP9 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.\n");

        return AVERROR(EINVAL);

    }

    switch (codec->codec_type) {

    case AVMEDIA_TYPE_VIDEO:

        put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);

        if(   st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0

           && 1.0/av_q2d(st->avg_frame_rate) > av_q2d(codec->time_base))

            put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1E9 / av_q2d(st->avg_frame_rate));

        else

            put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, av_q2d(codec->time_base)*1E9);

        if (!native_id &&

            ff_codec_get_tag(ff_codec_movvideo_tags, codec->codec_id) &&

            (!ff_codec_get_tag(ff_codec_bmp_tags,   codec->codec_id) ||

             codec->codec_id == AV_CODEC_ID_SVQ1 ||

             codec->codec_id == AV_CODEC_ID_SVQ3 ||

             codec->codec_id == AV_CODEC_ID_CINEPAK))

            qt_id = 1;

        if (qt_id)

            put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME");

        else if (!native_id) {

            // if there is no mkv-specific codec ID, use VFW mode

            put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC");

            mkv->tracks[i].write_dts = 1;

        }

        subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);

        // XXX: interlace flag?

        put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);

        put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);

        if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) ||

            (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) {

            int st_mode = MATROSKA_VIDEO_STEREO_MODE_COUNT;

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

                if (!strcmp(tag->value, ff_matroska_video_stereo_mode[j])){

                    st_mode = j;

                    break;

                }

            if (mkv_write_stereo_mode(s, pb, st_mode, mkv->mode) < 0)

                return AVERROR(EINVAL);

            switch (st_mode) {

            case 1:

            case 8:

            case 9:

            case 11:

                display_width_div = 2;

                break;

            case 2:

            case 3:

            case 6:

            case 7:

                display_height_div = 2;

                break;

            }

        }

        if ((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) ||

            (tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) ||

            (codec->pix_fmt == AV_PIX_FMT_YUVA420P)) {

            put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1);

        }

        if (st->sample_aspect_ratio.num) {

            int64_t d_width = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);

            if (d_width > INT_MAX) {

                av_log(s, AV_LOG_ERROR, "Overflow in display width\n");

                return AVERROR(EINVAL);

            }

            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div);

            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);

        } else if (display_width_div != 1 || display_height_div != 1) {

            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->width / display_width_div);

            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);

        }

        if (codec->codec_id == AV_CODEC_ID_RAWVIDEO) {

            uint32_t color_space = av_le2ne32(codec->codec_tag);

            put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space));

        }

        end_ebml_master(pb, subinfo);

        break;

    case AVMEDIA_TYPE_AUDIO:

        put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);

        if (!native_id)

            // no mkv-specific ID, use ACM mode

            put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM");

        subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0);

        put_ebml_uint  (pb, MATROSKA_ID_AUDIOCHANNELS    , codec->channels);

        put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);

        if (output_sample_rate)

            put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);

        if (bit_depth)

            put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth);

        end_ebml_master(pb, subinfo);

        break;

    case AVMEDIA_TYPE_SUBTITLE:

        if (!native_id) {

            av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id);

            return AVERROR(ENOSYS);

        }

        if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT)

            native_id = MATROSKA_TRACK_TYPE_SUBTITLE;

        put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id);

        break;

    default:

        av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n");

        return AVERROR(EINVAL);

    }

    if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) {

        ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id);

        if (ret < 0)

            return ret;

    }

    end_ebml_master(pb, track);

    return 0;

}


static int ffm_probe(AVProbeData *p)

{

    if (p->buf_size >= 4 &&

        p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' &&

        p->buf[3] == '1')

        return AVPROBE_SCORE_MAX + 1;

    return 0;

}


static void win32_aio_process_completion(QEMUWin32AIOState *s,

    QEMUWin32AIOCB *waiocb, DWORD count)

{

    int ret;

    s->count--;

    if (waiocb->ov.Internal != 0) {

        ret = -EIO;

    } else {

        ret = 0;

        if (count < waiocb->nbytes) {

            /* Short reads mean EOF, pad with zeros. */

            if (waiocb->is_read) {

                qemu_iovec_memset(waiocb->qiov, count, 0,

                    waiocb->qiov->size - count);

            } else {

                ret = -EINVAL;

            }

       }

    }

    if (!waiocb->is_linear) {

        if (ret == 0 && waiocb->is_read) {

            QEMUIOVector *qiov = waiocb->qiov;

            char *p = waiocb->buf;

            int i;

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

                memcpy(qiov->iov[i].iov_base, p, qiov->iov[i].iov_len);

                p += qiov->iov[i].iov_len;

            }

            qemu_vfree(waiocb->buf);

        }

    }

    waiocb->common.cb(waiocb->common.opaque, ret);

    qemu_aio_release(waiocb);

}


static void compute_pkt_fields(AVFormatContext *s, AVStream *st,

                               AVCodecParserContext *pc, AVPacket *pkt,

                               int64_t next_dts, int64_t next_pts)

{

    int num, den, presentation_delayed, delay, i;

    int64_t offset;

    AVRational duration;

    int onein_oneout = st->codec->codec_id != AV_CODEC_ID_H264 &&

                       st->codec->codec_id != AV_CODEC_ID_HEVC;

    if (s->flags & AVFMT_FLAG_NOFILLIN)

        return;

    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pkt->dts != AV_NOPTS_VALUE) {

        if (pkt->dts == pkt->pts && st->last_dts_for_order_check != AV_NOPTS_VALUE) {

            if (st->last_dts_for_order_check <= pkt->dts) {

                st->dts_ordered++;

            } else {

                av_log(s, st->dts_misordered ? AV_LOG_DEBUG : AV_LOG_WARNING,

                       "DTS %"PRIi64" < %"PRIi64" out of order\n",

                       pkt->dts,

                       st->last_dts_for_order_check);

                st->dts_misordered++;

            }

            if (st->dts_ordered + st->dts_misordered > 250) {

                st->dts_ordered    >>= 1;

                st->dts_misordered >>= 1;

            }

        }

        st->last_dts_for_order_check = pkt->dts;

        if (st->dts_ordered < 8*st->dts_misordered && pkt->dts == pkt->pts)

            pkt->dts = AV_NOPTS_VALUE;

    }

    if ((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE)

        pkt->dts = AV_NOPTS_VALUE;

    if (pc && pc->pict_type == AV_PICTURE_TYPE_B

        && !st->codec->has_b_frames)

        //FIXME Set low_delay = 0 when has_b_frames = 1

        st->codec->has_b_frames = 1;

    /* do we have a video B-frame ? */

    delay = st->codec->has_b_frames;

    presentation_delayed = 0;

    /* XXX: need has_b_frame, but cannot get it if the codec is

     *  not initialized */

    if (delay &&

        pc && pc->pict_type != AV_PICTURE_TYPE_B)

        presentation_delayed = 1;

    if (pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE &&

        st->pts_wrap_bits < 63 &&

        pkt->dts - (1LL << (st->pts_wrap_bits - 1)) > pkt->pts) {

        if (is_relative(st->cur_dts) || pkt->dts - (1LL<<(st->pts_wrap_bits - 1)) > st->cur_dts) {

            pkt->dts -= 1LL << st->pts_wrap_bits;

        } else

            pkt->pts += 1LL << st->pts_wrap_bits;

    }

    /* Some MPEG-2 in MPEG-PS lack dts (issue #171 / input_file.mpg).

     * We take the conservative approach and discard both.

     * Note: If this is misbehaving for an H.264 file, then possibly

     * presentation_delayed is not set correctly. */

    if (delay == 1 && pkt->dts == pkt->pts &&

        pkt->dts != AV_NOPTS_VALUE && presentation_delayed) {

        av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination %"PRIi64"\n", pkt->dts);

        if (    strcmp(s->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2")

             && strcmp(s->iformat->name, "flv")) // otherwise we discard correct timestamps for vc1-wmapro.ism

            pkt->dts = AV_NOPTS_VALUE;

    }

    duration = av_mul_q((AVRational) {pkt->duration, 1}, st->time_base);

    if (pkt->duration == 0) {

        ff_compute_frame_duration(s, &num, &den, st, pc, pkt);

        if (den && num) {

            duration = (AVRational) {num, den};

            pkt->duration = av_rescale_rnd(1,

                                           num * (int64_t) st->time_base.den,

                                           den * (int64_t) st->time_base.num,

                                           AV_ROUND_DOWN);

        }

    }

    if (pkt->duration != 0 && (s->packet_buffer || s->parse_queue))

        update_initial_durations(s, st, pkt->stream_index, pkt->duration);

    /* Correct timestamps with byte offset if demuxers only have timestamps

     * on packet boundaries */

    if (pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size) {

        /* this will estimate bitrate based on this frame's duration and size */

        offset = av_rescale(pc->offset, pkt->duration, pkt->size);

        if (pkt->pts != AV_NOPTS_VALUE)

            pkt->pts += offset;

        if (pkt->dts != AV_NOPTS_VALUE)

            pkt->dts += offset;

    }

    /* This may be redundant, but it should not hurt. */

    if (pkt->dts != AV_NOPTS_VALUE &&

        pkt->pts != AV_NOPTS_VALUE &&

        pkt->pts > pkt->dts)

        presentation_delayed = 1;

    av_dlog(NULL,

            "IN delayed:%d pts:%s, dts:%s cur_dts:%s st:%d pc:%p duration:%d delay:%d onein_oneout:%d\n",

            presentation_delayed, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts),

            pkt->stream_index, pc, pkt->duration, delay, onein_oneout);

    /* Interpolate PTS and DTS if they are not present. We skip H264

     * currently because delay and has_b_frames are not reliably set. */

    if ((delay == 0 || (delay == 1 && pc)) &&

        onein_oneout) {

        if (presentation_delayed) {

            /* DTS = decompression timestamp */

            /* PTS = presentation timestamp */

            if (pkt->dts == AV_NOPTS_VALUE)

                pkt->dts = st->last_IP_pts;

            update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts, pkt);

            if (pkt->dts == AV_NOPTS_VALUE)

                pkt->dts = st->cur_dts;

            /* This is tricky: the dts must be incremented by the duration

             * of the frame we are displaying, i.e. the last I- or P-frame. */

            if (st->last_IP_duration == 0)

                st->last_IP_duration = pkt->duration;

            if (pkt->dts != AV_NOPTS_VALUE)

                st->cur_dts = pkt->dts + st->last_IP_duration;

            if (pkt->dts != AV_NOPTS_VALUE &&

                pkt->pts == AV_NOPTS_VALUE &&

                st->last_IP_duration > 0 &&

                (st->cur_dts - next_dts) <= 1 &&

                next_dts != next_pts &&

                next_pts != AV_NOPTS_VALUE)

                pkt->pts = next_dts;

            st->last_IP_duration = pkt->duration;

            st->last_IP_pts      = pkt->pts;

            /* Cannot compute PTS if not present (we can compute it only

             * by knowing the future. */

        } else if (pkt->pts != AV_NOPTS_VALUE ||

                   pkt->dts != AV_NOPTS_VALUE ||

                   pkt->duration                ) {

            /* presentation is not delayed : PTS and DTS are the same */

            if (pkt->pts == AV_NOPTS_VALUE)

                pkt->pts = pkt->dts;

            update_initial_timestamps(s, pkt->stream_index, pkt->pts,

                                      pkt->pts, pkt);

            if (pkt->pts == AV_NOPTS_VALUE)

                pkt->pts = st->cur_dts;

            pkt->dts = pkt->pts;

            if (pkt->pts != AV_NOPTS_VALUE)

                st->cur_dts = av_add_stable(st->time_base, pkt->pts, duration, 1);

        }

    }

    if (pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY && has_decode_delay_been_guessed(st)) {

        st->pts_buffer[0] = pkt->pts;

        for (i = 0; i<delay && st->pts_buffer[i] > st->pts_buffer[i + 1]; i++)

            FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i + 1]);

        pkt->dts = select_from_pts_buffer(st, st->pts_buffer, pkt->dts);

    }

    // We skipped it above so we try here.

    if (!onein_oneout)

        // This should happen on the first packet

        update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts, pkt);

    if (pkt->dts > st->cur_dts)

        st->cur_dts = pkt->dts;

    av_dlog(NULL, "OUTdelayed:%d/%d pts:%s, dts:%s cur_dts:%s\n",

            presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts));

    /* update flags */

    if (is_intra_only(st->codec))

        pkt->flags |= AV_PKT_FLAG_KEY;

    if (pc)

        pkt->convergence_duration = pc->convergence_duration;

}


static inline int vertClassify_altivec(uint8_t src[], int stride, PPContext *c) {

    /*

    this code makes no assumption on src or stride.

    One could remove the recomputation of the perm

    vector by assuming (stride % 16) == 0, unfortunately

    this is not always true.

    */

    DECLARE_ALIGNED(16, short, data)[8] =

                    {

                        ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1,

                        data[0] * 2 + 1,

                        c->QP * 2,

                        c->QP * 4

                    };

    int numEq;

    uint8_t *src2 = src;

    vector signed short v_dcOffset;

    vector signed short v2QP;

    vector unsigned short v4QP;

    vector unsigned short v_dcThreshold;

    const int properStride = (stride % 16);

    const int srcAlign = ((unsigned long)src2 % 16);

    const int two_vectors = ((srcAlign > 8) || properStride) ? 1 : 0;

    const vector signed int zero = vec_splat_s32(0);

    const vector signed short mask = vec_splat_s16(1);

    vector signed int v_numEq = vec_splat_s32(0);

    vector signed short v_data = vec_ld(0, data);

    vector signed short v_srcAss0, v_srcAss1, v_srcAss2, v_srcAss3,

                        v_srcAss4, v_srcAss5, v_srcAss6, v_srcAss7;

//FIXME avoid this mess if possible

    register int j0 = 0,

                 j1 = stride,

                 j2 = 2 * stride,

                 j3 = 3 * stride,

                 j4 = 4 * stride,

                 j5 = 5 * stride,

                 j6 = 6 * stride,

                 j7 = 7 * stride;

    vector unsigned char v_srcA0, v_srcA1, v_srcA2, v_srcA3,

                         v_srcA4, v_srcA5, v_srcA6, v_srcA7;

    v_dcOffset = vec_splat(v_data, 0);

    v_dcThreshold = (vector unsigned short)vec_splat(v_data, 1);

    v2QP = vec_splat(v_data, 2);

    v4QP = (vector unsigned short)vec_splat(v_data, 3);

    src2 += stride * 4;

#define LOAD_LINE(i)                                                    \

    {                                                                   \

    vector unsigned char perm##i = vec_lvsl(j##i, src2);                \

    vector unsigned char v_srcA2##i;                                    \

    vector unsigned char v_srcA1##i = vec_ld(j##i, src2);               \

    if (two_vectors)                                                    \

        v_srcA2##i = vec_ld(j##i + 16, src2);                           \

    v_srcA##i =                                                         \

        vec_perm(v_srcA1##i, v_srcA2##i, perm##i);                      \

    v_srcAss##i =                                                       \

        (vector signed short)vec_mergeh((vector signed char)zero,       \

                                        (vector signed char)v_srcA##i); }

#define LOAD_LINE_ALIGNED(i)                                            \

    v_srcA##i = vec_ld(j##i, src2);                                     \

    v_srcAss##i =                                                       \

        (vector signed short)vec_mergeh((vector signed char)zero,       \

                                        (vector signed char)v_srcA##i)

    /* Special-casing the aligned case is worthwhile, as all calls from

     * the (transposed) horizontable deblocks will be aligned, in addition

     * to the naturally aligned vertical deblocks. */

    if (properStride && srcAlign) {

        LOAD_LINE_ALIGNED(0);

        LOAD_LINE_ALIGNED(1);

        LOAD_LINE_ALIGNED(2);

        LOAD_LINE_ALIGNED(3);

        LOAD_LINE_ALIGNED(4);

        LOAD_LINE_ALIGNED(5);

        LOAD_LINE_ALIGNED(6);

        LOAD_LINE_ALIGNED(7);

    } else {

        LOAD_LINE(0);

        LOAD_LINE(1);

        LOAD_LINE(2);

        LOAD_LINE(3);

        LOAD_LINE(4);

        LOAD_LINE(5);

        LOAD_LINE(6);

        LOAD_LINE(7);

    }

#undef LOAD_LINE

#undef LOAD_LINE_ALIGNED

#define ITER(i, j)                                                      \

    const vector signed short v_diff##i =                               \

        vec_sub(v_srcAss##i, v_srcAss##j);                              \

    const vector signed short v_sum##i =                                \

        vec_add(v_diff##i, v_dcOffset);                                 \

    const vector signed short v_comp##i =                               \

        (vector signed short)vec_cmplt((vector unsigned short)v_sum##i, \

                                       v_dcThreshold);                  \

    const vector signed short v_part##i = vec_and(mask, v_comp##i);

    {

        ITER(0, 1)

        ITER(1, 2)

        ITER(2, 3)

        ITER(3, 4)

        ITER(4, 5)

        ITER(5, 6)

        ITER(6, 7)

        v_numEq = vec_sum4s(v_part0, v_numEq);

        v_numEq = vec_sum4s(v_part1, v_numEq);

        v_numEq = vec_sum4s(v_part2, v_numEq);

        v_numEq = vec_sum4s(v_part3, v_numEq);

        v_numEq = vec_sum4s(v_part4, v_numEq);

        v_numEq = vec_sum4s(v_part5, v_numEq);

        v_numEq = vec_sum4s(v_part6, v_numEq);

    }

#undef ITER

    v_numEq = vec_sums(v_numEq, zero);

    v_numEq = vec_splat(v_numEq, 3);

    vec_ste(v_numEq, 0, &numEq);

    if (numEq > c->ppMode.flatnessThreshold){

        const vector unsigned char mmoP1 = (const vector unsigned char)

            {0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,

             0x00, 0x01, 0x12, 0x13, 0x08, 0x09, 0x1A, 0x1B};

        const vector unsigned char mmoP2 = (const vector unsigned char)

            {0x04, 0x05, 0x16, 0x17, 0x0C, 0x0D, 0x1E, 0x1F,

             0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f};

        const vector unsigned char mmoP = (const vector unsigned char)

            vec_lvsl(8, (unsigned char*)0);

        vector signed short mmoL1 = vec_perm(v_srcAss0, v_srcAss2, mmoP1);

        vector signed short mmoL2 = vec_perm(v_srcAss4, v_srcAss6, mmoP2);

        vector signed short mmoL = vec_perm(mmoL1, mmoL2, mmoP);

        vector signed short mmoR1 = vec_perm(v_srcAss5, v_srcAss7, mmoP1);

        vector signed short mmoR2 = vec_perm(v_srcAss1, v_srcAss3, mmoP2);

        vector signed short mmoR = vec_perm(mmoR1, mmoR2, mmoP);

        vector signed short mmoDiff = vec_sub(mmoL, mmoR);

        vector unsigned short mmoSum = (vector unsigned short)vec_add(mmoDiff, v2QP);

        if (vec_any_gt(mmoSum, v4QP))

            return 0;

        else

            return 1;

    }

    else return 2;

}


static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)

{

    VC1Context * const v = avctx->priv_data;

    MpegEncContext * const s = &v->s;

    struct vaapi_context * const vactx = avctx->hwaccel_context;

    VAPictureParameterBufferVC1 *pic_param;

    av_dlog(avctx, "vaapi_vc1_start_frame()\n");

    vactx->slice_param_size = sizeof(VASliceParameterBufferVC1);

    /* Fill in VAPictureParameterBufferVC1 */

    pic_param = ff_vaapi_alloc_pic_param(vactx, sizeof(VAPictureParameterBufferVC1));

    if (!pic_param)

        return -1;

    pic_param->forward_reference_picture                            = VA_INVALID_ID;

    pic_param->backward_reference_picture                           = VA_INVALID_ID;

    pic_param->inloop_decoded_picture                               = VA_INVALID_ID;

    pic_param->sequence_fields.value                                = 0; /* reset all bits */

    pic_param->sequence_fields.bits.pulldown                        = v->broadcast;

    pic_param->sequence_fields.bits.interlace                       = v->interlace;

    pic_param->sequence_fields.bits.tfcntrflag                      = v->tfcntrflag;

    pic_param->sequence_fields.bits.finterpflag                     = v->finterpflag;

    pic_param->sequence_fields.bits.psf                             = v->psf;

    pic_param->sequence_fields.bits.multires                        = v->multires;

    pic_param->sequence_fields.bits.overlap                         = v->overlap;

    pic_param->sequence_fields.bits.syncmarker                      = v->resync_marker;

    pic_param->sequence_fields.bits.rangered                        = v->rangered;

    pic_param->sequence_fields.bits.max_b_frames                    = s->avctx->max_b_frames;

#if VA_CHECK_VERSION(0,32,0)

    pic_param->sequence_fields.bits.profile                         = v->profile;

#endif

    pic_param->coded_width                                          = s->avctx->coded_width;

    pic_param->coded_height                                         = s->avctx->coded_height;

    pic_param->entrypoint_fields.value                              = 0; /* reset all bits */

    pic_param->entrypoint_fields.bits.broken_link                   = v->broken_link;

    pic_param->entrypoint_fields.bits.closed_entry                  = v->closed_entry;

    pic_param->entrypoint_fields.bits.panscan_flag                  = v->panscanflag;

    pic_param->entrypoint_fields.bits.loopfilter                    = s->loop_filter;

    pic_param->conditional_overlap_flag                             = v->condover;

    pic_param->fast_uvmc_flag                                       = v->fastuvmc;

    pic_param->range_mapping_fields.value                           = 0; /* reset all bits */

    pic_param->range_mapping_fields.bits.luma_flag                  = v->range_mapy_flag;

    pic_param->range_mapping_fields.bits.luma                       = v->range_mapy;

    pic_param->range_mapping_fields.bits.chroma_flag                = v->range_mapuv_flag;

    pic_param->range_mapping_fields.bits.chroma                     = v->range_mapuv;

    pic_param->b_picture_fraction                                   = v->bfraction_lut_index;

    pic_param->cbp_table                                            = v->cbpcy_vlc ? v->cbpcy_vlc - ff_vc1_cbpcy_p_vlc : 0;

    pic_param->mb_mode_table                                        = 0; /* XXX: interlaced frame */

    pic_param->range_reduction_frame                                = v->rangeredfrm;

    pic_param->rounding_control                                     = v->rnd;

    pic_param->post_processing                                      = v->postproc;

    pic_param->picture_resolution_index                             = v->respic;

    pic_param->luma_scale                                           = v->lumscale;

    pic_param->luma_shift                                           = v->lumshift;

    pic_param->picture_fields.value                                 = 0; /* reset all bits */

    pic_param->picture_fields.bits.picture_type                     = vc1_get_PTYPE(v);

    pic_param->picture_fields.bits.frame_coding_mode                = v->fcm;

    pic_param->picture_fields.bits.top_field_first                  = v->tff;

    pic_param->picture_fields.bits.is_first_field                   = v->fcm == 0; /* XXX: interlaced frame */

    pic_param->picture_fields.bits.intensity_compensation           = v->mv_mode == MV_PMODE_INTENSITY_COMP;

    pic_param->raw_coding.value                                     = 0; /* reset all bits */

    pic_param->raw_coding.flags.mv_type_mb                          = v->mv_type_is_raw;

    pic_param->raw_coding.flags.direct_mb                           = v->dmb_is_raw;

    pic_param->raw_coding.flags.skip_mb                             = v->skip_is_raw;

    pic_param->raw_coding.flags.field_tx                            = 0; /* XXX: interlaced frame */

    pic_param->raw_coding.flags.forward_mb                          = 0; /* XXX: interlaced frame */

    pic_param->raw_coding.flags.ac_pred                             = v->acpred_is_raw;

    pic_param->raw_coding.flags.overflags                           = v->overflg_is_raw;

    pic_param->bitplane_present.value                               = 0; /* reset all bits */

    pic_param->bitplane_present.flags.bp_mv_type_mb                 = vc1_has_MVTYPEMB_bitplane(v);

    pic_param->bitplane_present.flags.bp_direct_mb                  = vc1_has_DIRECTMB_bitplane(v);

    pic_param->bitplane_present.flags.bp_skip_mb                    = vc1_has_SKIPMB_bitplane(v);

    pic_param->bitplane_present.flags.bp_field_tx                   = 0; /* XXX: interlaced frame */

    pic_param->bitplane_present.flags.bp_forward_mb                 = 0; /* XXX: interlaced frame */

    pic_param->bitplane_present.flags.bp_ac_pred                    = vc1_has_ACPRED_bitplane(v);

    pic_param->bitplane_present.flags.bp_overflags                  = vc1_has_OVERFLAGS_bitplane(v);

    pic_param->reference_fields.value                               = 0; /* reset all bits */

    pic_param->reference_fields.bits.reference_distance_flag        = v->refdist_flag;

    pic_param->reference_fields.bits.reference_distance             = 0; /* XXX: interlaced frame */

    pic_param->reference_fields.bits.num_reference_pictures         = 0; /* XXX: interlaced frame */

    pic_param->reference_fields.bits.reference_field_pic_indicator  = 0; /* XXX: interlaced frame */

    pic_param->mv_fields.value                                      = 0; /* reset all bits */

    pic_param->mv_fields.bits.mv_mode                               = vc1_get_MVMODE(v);

    pic_param->mv_fields.bits.mv_mode2                              = vc1_get_MVMODE2(v);

    pic_param->mv_fields.bits.mv_table                              = s->mv_table_index;

    pic_param->mv_fields.bits.two_mv_block_pattern_table            = 0; /* XXX: interlaced frame */

    pic_param->mv_fields.bits.four_mv_switch                        = 0; /* XXX: interlaced frame */

    pic_param->mv_fields.bits.four_mv_block_pattern_table           = 0; /* XXX: interlaced frame */

    pic_param->mv_fields.bits.extended_mv_flag                      = v->extended_mv;

    pic_param->mv_fields.bits.extended_mv_range                     = v->mvrange;

    pic_param->mv_fields.bits.extended_dmv_flag                     = v->extended_dmv;

    pic_param->mv_fields.bits.extended_dmv_range                    = 0; /* XXX: interlaced frame */

    pic_param->pic_quantizer_fields.value                           = 0; /* reset all bits */

    pic_param->pic_quantizer_fields.bits.dquant                     = v->dquant;

    pic_param->pic_quantizer_fields.bits.quantizer                  = v->quantizer_mode;

    pic_param->pic_quantizer_fields.bits.half_qp                    = v->halfpq;

    pic_param->pic_quantizer_fields.bits.pic_quantizer_scale        = v->pq;

    pic_param->pic_quantizer_fields.bits.pic_quantizer_type         = v->pquantizer;

    pic_param->pic_quantizer_fields.bits.dq_frame                   = v->dquantfrm;

    pic_param->pic_quantizer_fields.bits.dq_profile                 = v->dqprofile;

    pic_param->pic_quantizer_fields.bits.dq_sb_edge                 = v->dqprofile == DQPROFILE_SINGLE_EDGE  ? v->dqsbedge : 0;

    pic_param->pic_quantizer_fields.bits.dq_db_edge                 = v->dqprofile == DQPROFILE_DOUBLE_EDGES ? v->dqsbedge : 0;

    pic_param->pic_quantizer_fields.bits.dq_binary_level            = v->dqbilevel;

    pic_param->pic_quantizer_fields.bits.alt_pic_quantizer          = v->altpq;

    pic_param->transform_fields.value                               = 0; /* reset all bits */

    pic_param->transform_fields.bits.variable_sized_transform_flag  = v->vstransform;

    pic_param->transform_fields.bits.mb_level_transform_type_flag   = v->ttmbf;

    pic_param->transform_fields.bits.frame_level_transform_type     = vc1_get_TTFRM(v);

    pic_param->transform_fields.bits.transform_ac_codingset_idx1    = v->c_ac_table_index;

    pic_param->transform_fields.bits.transform_ac_codingset_idx2    = v->y_ac_table_index;

    pic_param->transform_fields.bits.intra_transform_dc_table       = v->s.dc_table_index;

    switch (s->pict_type) {

    case AV_PICTURE_TYPE_B:

        pic_param->backward_reference_picture = ff_vaapi_get_surface_id(&s->next_picture.f);

        // fall-through

    case AV_PICTURE_TYPE_P:

        pic_param->forward_reference_picture = ff_vaapi_get_surface_id(&s->last_picture.f);

        break;

    }

    if (pic_param->bitplane_present.value) {

        uint8_t *bitplane;

        const uint8_t *ff_bp[3];

        int x, y, n;

        switch (s->pict_type) {

        case AV_PICTURE_TYPE_P:

            ff_bp[0] = pic_param->bitplane_present.flags.bp_direct_mb  ? v->direct_mb_plane    : NULL;

            ff_bp[1] = pic_param->bitplane_present.flags.bp_skip_mb    ? s->mbskip_table       : NULL;

            ff_bp[2] = pic_param->bitplane_present.flags.bp_mv_type_mb ? v->mv_type_mb_plane   : NULL;

            break;

        case AV_PICTURE_TYPE_B:

            if (!v->bi_type) {

                ff_bp[0] = pic_param->bitplane_present.flags.bp_direct_mb ? v->direct_mb_plane : NULL;

                ff_bp[1] = pic_param->bitplane_present.flags.bp_skip_mb   ? s->mbskip_table    : NULL;

                ff_bp[2] = NULL; /* XXX: interlaced frame (FORWARD plane) */

                break;

            }

            /* fall-through (BI-type) */

        case AV_PICTURE_TYPE_I:

            ff_bp[0] = NULL; /* XXX: interlaced frame (FIELDTX plane) */

            ff_bp[1] = pic_param->bitplane_present.flags.bp_ac_pred    ? v->acpred_plane       : NULL;

            ff_bp[2] = pic_param->bitplane_present.flags.bp_overflags  ? v->over_flags_plane   : NULL;

            break;

        default:

            ff_bp[0] = NULL;

            ff_bp[1] = NULL;

            ff_bp[2] = NULL;

            break;

        }

        bitplane = ff_vaapi_alloc_bitplane(vactx, (s->mb_width * s->mb_height + 1) / 2);

        if (!bitplane)

            return -1;

        n = 0;

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

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

                vc1_pack_bitplanes(bitplane, n, ff_bp, x, y, s->mb_stride);

        if (n & 1) /* move last nibble to the high order */

            bitplane[n/2] <<= 4;

    }

    return 0;

}


static int dxv_decompress_raw(AVCodecContext *avctx)
{
    DXVContext *ctx = avctx->priv_data;
    GetByteContext *gbc = &ctx->gbc;
    bytestream2_get_buffer(gbc, ctx->tex_data, ctx->tex_size);
    return 0;
}


static int of_dpa_cmd_group_add(OfDpa *of_dpa, uint32_t group_id,

                                RockerTlv **group_tlvs)

{

    OfDpaGroup *group = of_dpa_group_find(of_dpa, group_id);

    int err;

    if (group) {

        return -ROCKER_EEXIST;

    }

    group = of_dpa_group_alloc(group_id);

    if (!group) {

        return -ROCKER_ENOMEM;

    }

    err = of_dpa_cmd_group_do(of_dpa, group_id, group, group_tlvs);

    if (err) {

        goto err_cmd_add;

    }

    err = of_dpa_group_add(of_dpa, group);

    if (err) {

        goto err_cmd_add;

    }

    return ROCKER_OK;

err_cmd_add:

    g_free(group);

    return err;

}


static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, int (*read_child)(), int ctx_size, enum MXFMetadataSetType type)

{

    ByteIOContext *pb = mxf->fc->pb;

    MXFMetadataSet *ctx = ctx_size ? av_mallocz(ctx_size) : mxf;

    uint64_t klv_end = url_ftell(pb) + klv->length;

    if (!ctx)

        return -1;

    while (url_ftell(pb) + 4 < klv_end) {

        int tag = get_be16(pb);

        int size = get_be16(pb); /* KLV specified by 0x53 */

        uint64_t next = url_ftell(pb) + size;

        UID uid;

        if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */

            av_log(mxf->fc, AV_LOG_ERROR, "local tag 0x%04X with 0 size\n", tag);

            continue;

        }

        if (tag > 0x7FFF) { /* dynamic tag */

            int i;

            for (i = 0; i < mxf->local_tags_count; i++) {

                int local_tag = AV_RB16(mxf->local_tags+i*18);

                if (local_tag == tag) {

                    memcpy(uid, mxf->local_tags+i*18+2, 16);

                    dprintf(mxf->fc, "local tag 0x%04X\n", local_tag);

#ifdef DEBUG

                    PRINT_KEY(mxf->fc, "uid", uid);

#endif

                }

            }

        }

        if (ctx_size && tag == 0x3C0A)

            get_buffer(pb, ctx->uid, 16);

        else

            read_child(ctx, pb, tag, size, uid);

        url_fseek(pb, next, SEEK_SET);

    }

    if (ctx_size) ctx->type = type;

    return ctx_size ? mxf_add_metadata_set(mxf, ctx) : 0;

}


static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,

                      int *got_packet)

{

    X264Context *x4 = ctx->priv_data;

    x264_nal_t *nal;

    int nnal, i, ret;

    x264_picture_t pic_out = {0};

    int pict_type;

    x264_picture_init( &x4->pic );

    x4->pic.img.i_csp   = x4->params.i_csp;

    if (x264_bit_depth > 8)

        x4->pic.img.i_csp |= X264_CSP_HIGH_DEPTH;

    x4->pic.img.i_plane = avfmt2_num_planes(ctx->pix_fmt);

    if (frame) {

        for (i = 0; i < x4->pic.img.i_plane; i++) {

            x4->pic.img.plane[i]    = frame->data[i];

            x4->pic.img.i_stride[i] = frame->linesize[i];

        }

        x4->pic.i_pts  = frame->pts;

        switch (frame->pict_type) {

        case AV_PICTURE_TYPE_I:

            x4->pic.i_type = x4->forced_idr > 0 ? X264_TYPE_IDR

                                                : X264_TYPE_KEYFRAME;

            break;

        case AV_PICTURE_TYPE_P:

            x4->pic.i_type = X264_TYPE_P;

            break;

        case AV_PICTURE_TYPE_B:

            x4->pic.i_type = X264_TYPE_B;

            break;

        default:

            x4->pic.i_type = X264_TYPE_AUTO;

            break;

        }

        reconfig_encoder(ctx, frame);

        if (x4->a53_cc) {

            void *sei_data;

            size_t sei_size;

            ret = ff_alloc_a53_sei(frame, 0, &sei_data, &sei_size);

            if (ret < 0) {

                av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");

            } else if (sei_data) {

                x4->pic.extra_sei.payloads = av_mallocz(sizeof(x4->pic.extra_sei.payloads[0]));

                if (x4->pic.extra_sei.payloads == NULL) {

                    av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");

                    av_free(sei_data);

                } else {

                    x4->pic.extra_sei.sei_free = av_free;

                    x4->pic.extra_sei.payloads[0].payload_size = sei_size;

                    x4->pic.extra_sei.payloads[0].payload = sei_data;

                    x4->pic.extra_sei.num_payloads = 1;

                    x4->pic.extra_sei.payloads[0].payload_type = 4;

                }

            }

        }

    }

    do {

        if (x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0)

            return AVERROR_EXTERNAL;

        ret = encode_nals(ctx, pkt, nal, nnal);

        if (ret < 0)

            return ret;

    } while (!ret && !frame && x264_encoder_delayed_frames(x4->enc));

    pkt->pts = pic_out.i_pts;

    pkt->dts = pic_out.i_dts;

    switch (pic_out.i_type) {

    case X264_TYPE_IDR:

    case X264_TYPE_I:

        pict_type = AV_PICTURE_TYPE_I;

        break;

    case X264_TYPE_P:

        pict_type = AV_PICTURE_TYPE_P;

        break;

    case X264_TYPE_B:

    case X264_TYPE_BREF:

        pict_type = AV_PICTURE_TYPE_B;

        break;

    default:

        pict_type = AV_PICTURE_TYPE_NONE;

    }

#if FF_API_CODED_FRAME

FF_DISABLE_DEPRECATION_WARNINGS

    ctx->coded_frame->pict_type = pict_type;

FF_ENABLE_DEPRECATION_WARNINGS

#endif

    pkt->flags |= AV_PKT_FLAG_KEY*pic_out.b_keyframe;

    if (ret) {

        ff_side_data_set_encoder_stats(pkt, (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA, NULL, 0, pict_type);

#if FF_API_CODED_FRAME

FF_DISABLE_DEPRECATION_WARNINGS

        ctx->coded_frame->quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA;

FF_ENABLE_DEPRECATION_WARNINGS

#endif

    }

    *got_packet = ret;

    return 0;

}


int flv_h263_decode_picture_header(MpegEncContext *s)

{

    int format, width, height;

    /* picture header */

    if (get_bits_long(&s->gb, 17) != 1) {

        av_log(s->avctx, AV_LOG_ERROR, "Bad picture start code\n");

        return -1;

    }

    format = get_bits(&s->gb, 5);

    if (format != 0 && format != 1) {

        av_log(s->avctx, AV_LOG_ERROR, "Bad picture format\n");

        return -1;

    }

    s->h263_flv = format+1;

    s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */

    format = get_bits(&s->gb, 3);

    switch (format) {

    case 0:

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

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

        break;

    case 1:

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

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

        break;

    case 2:

        width = 352;

        height = 288;

        break;

    case 3:

        width = 176;

        height = 144;

        break;

    case 4:

        width = 128;

        height = 96;

        break;

    case 5:

        width = 320;

        height = 240;

        break;

    case 6:

        width = 160;

        height = 120;

        break;

    default:

        width = height = 0;

        break;

    }

    if ((width == 0) || (height == 0))

        return -1;

    s->width = width;

    s->height = height;

    s->pict_type = I_TYPE + get_bits(&s->gb, 2);

    if (s->pict_type > P_TYPE)

        s->pict_type = P_TYPE;

    skip_bits1(&s->gb);	/* deblocking flag */

    s->qscale = get_bits(&s->gb, 5);

    s->h263_plus = 0;

    s->unrestricted_mv = 1;

    s->h263_long_vectors = 0;

    /* PEI */

    while (get_bits1(&s->gb) != 0) {

        skip_bits(&s->gb, 8);

    }

    s->f_code = 1;

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

        av_log(s->avctx, AV_LOG_DEBUG, "%c esc_type:%d, qp:%d num:%d\n",

               av_get_pict_type_char(s->pict_type), s->h263_flv-1, s->qscale, s->picture_number);

    }

    s->y_dc_scale_table=

    s->c_dc_scale_table= ff_mpeg1_dc_scale_table;

    return 0;

}


static void pci_msix(void)

{

    QVirtioPCIDevice *dev;

    QPCIBus *bus;

    QVirtQueuePCI *vqpci;

    QGuestAllocator *alloc;

    QVirtioBlkReq req;

    int n_size = TEST_IMAGE_SIZE / 2;

    void *addr;

    uint64_t req_addr;

    uint64_t capacity;

    uint32_t features;

    uint32_t free_head;

    uint8_t status;

    char *data;

    bus = pci_test_start();

    alloc = pc_alloc_init();

    dev = virtio_blk_pci_init(bus, PCI_SLOT);

    qpci_msix_enable(dev->pdev);

    qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);

    /* MSI-X is enabled */

    addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);

    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,

                                                    (uint64_t)(uintptr_t)addr);

    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);

    features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);

    features = features & ~(QVIRTIO_F_BAD_FEATURE |

                            (1u << VIRTIO_RING_F_INDIRECT_DESC) |

                            (1u << VIRTIO_RING_F_EVENT_IDX) |

                            (1u << VIRTIO_BLK_F_SCSI));

    qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);

    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,

                                                                    alloc, 0);

    qvirtqueue_pci_msix_setup(dev, vqpci, alloc, 1);

    qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);

    qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "

                                                    " 'size': %d } }", n_size);

    qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);

    capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,

                                                    (uint64_t)(uintptr_t)addr);

    g_assert_cmpint(capacity, ==, n_size / 512);

    /* Write request */

    req.type = VIRTIO_BLK_T_OUT;

    req.ioprio = 1;

    req.sector = 0;

    req.data = g_malloc0(512);

    strcpy(req.data, "TEST");

    req_addr = virtio_blk_request(alloc, &req, 512);

    g_free(req.data);

    free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);

    qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);

    qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);

    qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);

    qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,

                           QVIRTIO_BLK_TIMEOUT_US);

    status = readb(req_addr + 528);

    g_assert_cmpint(status, ==, 0);

    guest_free(alloc, req_addr);

    /* Read request */

    req.type = VIRTIO_BLK_T_IN;

    req.ioprio = 1;

    req.sector = 0;

    req.data = g_malloc0(512);

    req_addr = virtio_blk_request(alloc, &req, 512);

    g_free(req.data);

    free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);

    qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);

    qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);

    qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);

    qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,

                           QVIRTIO_BLK_TIMEOUT_US);

    status = readb(req_addr + 528);

    g_assert_cmpint(status, ==, 0);

    data = g_malloc0(512);

    memread(req_addr + 16, data, 512);

    g_assert_cmpstr(data, ==, "TEST");

    g_free(data);

    guest_free(alloc, req_addr);

    /* End test */

    guest_free(alloc, vqpci->vq.desc);

    pc_alloc_uninit(alloc);

    qpci_msix_disable(dev->pdev);

    qvirtio_pci_device_disable(dev);

    g_free(dev);

    qpci_free_pc(bus);

    test_end();

}


static void test_co_queue(void)

{

    Coroutine *c1;

    Coroutine *c2;

    c1 = qemu_coroutine_create(c1_fn);

    c2 = qemu_coroutine_create(c2_fn);

    qemu_coroutine_enter(c1, c2);

    memset(c1, 0xff, sizeof(Coroutine));

    qemu_coroutine_enter(c2, NULL);

}


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

{

    int compno;

    int x;

    int y;

    int width;

    int height;

    int *image_line;

    int frame_index;

    const int numcomps = image->numcomps;

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

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

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

            return 0;

        }

    }

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

        width  = avctx->width / image->comps[compno].dx;

        height = avctx->height / image->comps[compno].dy;

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

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

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

            for (x = 0; x < width; ++x)

                image_line[x] = frame->data[compno][frame_index++];

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

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

            }

        }

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

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

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

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

            }

        }

    }

    return 1;

}


static int url_alloc_for_protocol(URLContext **puc, struct URLProtocol *up,

                                  const char *filename, int flags,

                                  const AVIOInterruptCB *int_cb)

{

    URLContext *uc;

    int err;

#if CONFIG_NETWORK

    if (up->flags & URL_PROTOCOL_FLAG_NETWORK && !ff_network_init())

        return AVERROR(EIO);

#endif

    if ((flags & AVIO_FLAG_READ) && !up->url_read) {

        av_log(NULL, AV_LOG_ERROR,

               "Impossible to open the '%s' protocol for reading\n", up->name);

        return AVERROR(EIO);

    }

    if ((flags & AVIO_FLAG_WRITE) && !up->url_write) {

        av_log(NULL, AV_LOG_ERROR,

               "Impossible to open the '%s' protocol for writing\n", up->name);

        return AVERROR(EIO);

    }

    uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);

    if (!uc) {

        err = AVERROR(ENOMEM);

        goto fail;

    }

    uc->av_class = &ffurl_context_class;

    uc->filename = (char *)&uc[1];

    strcpy(uc->filename, filename);

    uc->prot            = up;

    uc->flags           = flags;

    uc->is_streamed     = 0; /* default = not streamed */

    uc->max_packet_size = 0; /* default: stream file */

    if (up->priv_data_size) {

        uc->priv_data = av_mallocz(up->priv_data_size);

        if (!uc->priv_data) {

            err = AVERROR(ENOMEM);

            goto fail;

        }

        if (up->priv_data_class) {

            int proto_len= strlen(up->name);

            char *start = strchr(uc->filename, ',');

            *(const AVClass **)uc->priv_data = up->priv_data_class;

            av_opt_set_defaults(uc->priv_data);

            if(!strncmp(up->name, uc->filename, proto_len) && uc->filename + proto_len == start){

                int ret= 0;

                char *p= start;

                char sep= *++p;

                char *key, *val;

                p++;

                while(ret >= 0 && (key= strchr(p, sep)) && p<key && (val = strchr(key+1, sep))){

                    *val= *key= 0;

                    ret= av_opt_set(uc->priv_data, p, key+1, 0);

                    if (ret == AVERROR_OPTION_NOT_FOUND)

                        av_log(uc, AV_LOG_ERROR, "Key '%s' not found.\n", p);

                    *val= *key= sep;

                    p= val+1;

                }

                if(ret<0 || p!=key){

                    av_log(uc, AV_LOG_ERROR, "Error parsing options string %s\n", start);

                    av_freep(&uc->priv_data);

                    av_freep(&uc);

                    err = AVERROR(EINVAL);

                    goto fail;

                }

                memmove(start, key+1, strlen(key));

            }

        }

    }

    if (int_cb)

        uc->interrupt_callback = *int_cb;

    *puc = uc;

    return 0;

fail:

    *puc = NULL;

    if (uc)

        av_freep(&uc->priv_data);

    av_freep(&uc);

#if CONFIG_NETWORK

    if (up->flags & URL_PROTOCOL_FLAG_NETWORK)

        ff_network_close();

#endif

    return err;

}


void ff_write_pass1_stats(MpegEncContext *s)

{

    snprintf(s->avctx->stats_out, 256,

             "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d "

             "fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d hbits:%d;\n",

             s->current_picture_ptr->f.display_picture_number,

             s->current_picture_ptr->f.coded_picture_number,

             s->pict_type,

             s->current_picture.f.quality,

             s->i_tex_bits,

             s->p_tex_bits,

             s->mv_bits,

             s->misc_bits,

             s->f_code,

             s->b_code,

             s->current_picture.mc_mb_var_sum,

             s->current_picture.mb_var_sum,

             s->i_count, s->skip_count,

             s->header_bits);

}


static bool is_zero_cluster(BlockDriverState *bs, int64_t start)

{

    BDRVQcow2State *s = bs->opaque;

    int nr;

    BlockDriverState *file;

    int64_t res = bdrv_get_block_status_above(bs, NULL, start,

                                              s->cluster_sectors, &nr, &file);

    return res >= 0 && ((res & BDRV_BLOCK_ZERO) || !(res & BDRV_BLOCK_DATA));

}


static int get_cluster_offset(BlockDriverState *bs,

                                    VmdkExtent *extent,

                                    VmdkMetaData *m_data,

                                    uint64_t offset,

                                    int allocate,

                                    uint64_t *cluster_offset)

{

    unsigned int l1_index, l2_offset, l2_index;

    int min_index, i, j;

    uint32_t min_count, *l2_table;

    bool zeroed = false;

    if (m_data) {

        m_data->valid = 0;

    }

    if (extent->flat) {

        *cluster_offset = extent->flat_start_offset;

        return VMDK_OK;

    }

    offset -= (extent->end_sector - extent->sectors) * SECTOR_SIZE;

    l1_index = (offset >> 9) / extent->l1_entry_sectors;

    if (l1_index >= extent->l1_size) {

        return VMDK_ERROR;

    }

    l2_offset = extent->l1_table[l1_index];

    if (!l2_offset) {

        return VMDK_UNALLOC;

    }

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

        if (l2_offset == extent->l2_cache_offsets[i]) {

            /* increment the hit count */

            if (++extent->l2_cache_counts[i] == 0xffffffff) {

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

                    extent->l2_cache_counts[j] >>= 1;

                }

            }

            l2_table = extent->l2_cache + (i * extent->l2_size);

            goto found;

        }

    }

    /* not found: load a new entry in the least used one */

    min_index = 0;

    min_count = 0xffffffff;

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

        if (extent->l2_cache_counts[i] < min_count) {

            min_count = extent->l2_cache_counts[i];

            min_index = i;

        }

    }

    l2_table = extent->l2_cache + (min_index * extent->l2_size);

    if (bdrv_pread(

                extent->file,

                (int64_t)l2_offset * 512,

                l2_table,

                extent->l2_size * sizeof(uint32_t)

            ) != extent->l2_size * sizeof(uint32_t)) {

        return VMDK_ERROR;

    }

    extent->l2_cache_offsets[min_index] = l2_offset;

    extent->l2_cache_counts[min_index] = 1;

 found:

    l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;

    *cluster_offset = le32_to_cpu(l2_table[l2_index]);

    if (extent->has_zero_grain && *cluster_offset == VMDK_GTE_ZEROED) {

        zeroed = true;

    }

    if (!*cluster_offset || zeroed) {

        if (!allocate) {

            return zeroed ? VMDK_ZEROED : VMDK_UNALLOC;

        }

        /* Avoid the L2 tables update for the images that have snapshots. */

        *cluster_offset = bdrv_getlength(extent->file);

        if (!extent->compressed) {

            bdrv_truncate(

                extent->file,

                *cluster_offset + (extent->cluster_sectors << 9)

            );

        }

        *cluster_offset >>= 9;

        l2_table[l2_index] = cpu_to_le32(*cluster_offset);

        /* First of all we write grain itself, to avoid race condition

         * that may to corrupt the image.

         * This problem may occur because of insufficient space on host disk

         * or inappropriate VM shutdown.

         */

        if (get_whole_cluster(

                bs, extent, *cluster_offset, offset, allocate) == -1) {

            return VMDK_ERROR;

        }

        if (m_data) {

            m_data->offset = *cluster_offset;

            m_data->l1_index = l1_index;

            m_data->l2_index = l2_index;

            m_data->l2_offset = l2_offset;

            m_data->valid = 1;

        }

    }

    *cluster_offset <<= 9;

    return VMDK_OK;

}


QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)

{

    QPCIBusSPAPR *ret;

    ret = g_malloc(sizeof(*ret));

    ret->alloc = alloc;

    ret->bus.io_readb = qpci_spapr_io_readb;

    ret->bus.io_readw = qpci_spapr_io_readw;

    ret->bus.io_readl = qpci_spapr_io_readl;

    ret->bus.io_writeb = qpci_spapr_io_writeb;

    ret->bus.io_writew = qpci_spapr_io_writew;

    ret->bus.io_writel = qpci_spapr_io_writel;

    ret->bus.config_readb = qpci_spapr_config_readb;

    ret->bus.config_readw = qpci_spapr_config_readw;

    ret->bus.config_readl = qpci_spapr_config_readl;

    ret->bus.config_writeb = qpci_spapr_config_writeb;

    ret->bus.config_writew = qpci_spapr_config_writew;

    ret->bus.config_writel = qpci_spapr_config_writel;

    ret->bus.iomap = qpci_spapr_iomap;

    ret->bus.iounmap = qpci_spapr_iounmap;

    /* FIXME: We assume the default location of the PHB for now.

     * Ideally we'd parse the device tree deposited in the guest to

     * get the window locations */

    ret->buid = 0x800000020000000ULL;

    ret->pio_cpu_base = SPAPR_PCI_WINDOW_BASE + SPAPR_PCI_IO_WIN_OFF;

    ret->pio.pci_base = 0;

    ret->pio.size = SPAPR_PCI_IO_WIN_SIZE;

    /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */

    ret->mmio32_cpu_base = SPAPR_PCI_WINDOW_BASE + SPAPR_PCI_MMIO32_WIN_OFF;

    ret->mmio32.pci_base = 0x80000000; /* 2 GiB */

    ret->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE;

    ret->pci_hole_start = 0xC0000000;

    ret->pci_hole_size =

        ret->mmio32.pci_base + ret->mmio32.size - ret->pci_hole_start;

    ret->pci_hole_alloc = 0;

    ret->pci_iohole_start = 0xc000;

    ret->pci_iohole_size =

        ret->pio.pci_base + ret->pio.size - ret->pci_iohole_start;

    ret->pci_iohole_alloc = 0;

    return &ret->bus;

}


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

                              int jobnr, int threadnr)

{

    VP56Context *s0 = avctx->priv_data;

    int is_alpha = (jobnr == 1);

    VP56Context *s = is_alpha ? s0->alpha_context : s0;

    AVFrame *const p = s->frames[VP56_FRAME_CURRENT];

    int mb_row, mb_col, mb_row_flip, mb_offset = 0;

    int block, y, uv;

    ptrdiff_t stride_y, stride_uv;

    int res;

    int damaged = 0;

    if (p->key_frame) {

        p->pict_type = AV_PICTURE_TYPE_I;

        s->default_models_init(s);

        for (block=0; block<s->mb_height*s->mb_width; block++)

            s->macroblocks[block].type = VP56_MB_INTRA;

    } else {

        p->pict_type = AV_PICTURE_TYPE_P;

        vp56_parse_mb_type_models(s);

        s->parse_vector_models(s);

        s->mb_type = VP56_MB_INTER_NOVEC_PF;

    }

    if (s->parse_coeff_models(s))

        goto next;

    memset(s->prev_dc, 0, sizeof(s->prev_dc));

    s->prev_dc[1][VP56_FRAME_CURRENT] = 128;

    s->prev_dc[2][VP56_FRAME_CURRENT] = 128;

    for (block=0; block < 4*s->mb_width+6; block++) {

        s->above_blocks[block].ref_frame = VP56_FRAME_NONE;

        s->above_blocks[block].dc_coeff = 0;

        s->above_blocks[block].not_null_dc = 0;

    }

    s->above_blocks[2*s->mb_width + 2].ref_frame = VP56_FRAME_CURRENT;

    s->above_blocks[3*s->mb_width + 4].ref_frame = VP56_FRAME_CURRENT;

    stride_y  = p->linesize[0];

    stride_uv = p->linesize[1];

    if (s->flip < 0)

        mb_offset = 7;

    /* main macroblocks loop */

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

        if (s->flip < 0)

            mb_row_flip = s->mb_height - mb_row - 1;

        else

            mb_row_flip = mb_row;

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

            s->left_block[block].ref_frame = VP56_FRAME_NONE;

            s->left_block[block].dc_coeff = 0;

            s->left_block[block].not_null_dc = 0;

        }

        memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx));

        memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last));

        s->above_block_idx[0] = 1;

        s->above_block_idx[1] = 2;

        s->above_block_idx[2] = 1;

        s->above_block_idx[3] = 2;

        s->above_block_idx[4] = 2*s->mb_width + 2 + 1;

        s->above_block_idx[5] = 3*s->mb_width + 4 + 1;

        s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y;

        s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y;

        s->block_offset[1] = s->block_offset[0] + 8;

        s->block_offset[3] = s->block_offset[2] + 8;

        s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv;

        s->block_offset[5] = s->block_offset[4];

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

            if (!damaged) {

                int ret = vp56_decode_mb(s, mb_row, mb_col, is_alpha);

                if (ret < 0)

                    damaged = 1;

            }

            if (damaged)

                vp56_conceal_mb(s, mb_row, mb_col, is_alpha);

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

                s->above_block_idx[y] += 2;

                s->block_offset[y] += 16;

            }

            for (uv=4; uv<6; uv++) {

                s->above_block_idx[uv] += 1;

                s->block_offset[uv] += 8;

            }

        }

    }

next:

    if (p->key_frame || s->golden_frame) {

        av_frame_unref(s->frames[VP56_FRAME_GOLDEN]);

        if ((res = av_frame_ref(s->frames[VP56_FRAME_GOLDEN], p)) < 0)

            return res;

    }

    av_frame_unref(s->frames[VP56_FRAME_PREVIOUS]);

    FFSWAP(AVFrame *, s->frames[VP56_FRAME_CURRENT],

                      s->frames[VP56_FRAME_PREVIOUS]);

    return 0;

}


static void pci_config(void)

{

    QVirtioPCIDevice *dev;

    QOSState *qs;

    int n_size = TEST_IMAGE_SIZE / 2;

    uint64_t capacity;

    qs = pci_test_start();

    dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);

    capacity = qvirtio_config_readq(&dev->vdev, 0);

    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);

    qvirtio_set_driver_ok(&dev->vdev);

    qmp_discard_response("{ 'execute': 'block_resize', "

                         " 'arguments': { 'device': 'drive0', "

                         " 'size': %d } }", n_size);

    qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);

    capacity = qvirtio_config_readq(&dev->vdev, 0);

    g_assert_cmpint(capacity, ==, n_size / 512);

    qvirtio_pci_device_disable(dev);

    g_free(dev);

    qtest_shutdown(qs);

}


static int draw_slice(AVFilterLink *inlink, int y0, int h, int slice_dir)

{

    AlphaExtractContext *extract = inlink->dst->priv;

    AVFilterBufferRef *cur_buf = inlink->cur_buf;

    AVFilterBufferRef *out_buf = inlink->dst->outputs[0]->out_buf;

    if (extract->is_packed_rgb) {

        int x, y;

        uint8_t *pin, *pout;

        for (y = y0; y < (y0 + h); y++) {

            pin = cur_buf->data[0] + y * cur_buf->linesize[0] + extract->rgba_map[A];

            pout = out_buf->data[0] + y * out_buf->linesize[0];

            for (x = 0; x < out_buf->video->w; x++) {

                *pout = *pin;

                pout += 1;

                pin += 4;

            }

        }

    } else if (cur_buf->linesize[A] == out_buf->linesize[Y]) {

        const int linesize = cur_buf->linesize[A];

        memcpy(out_buf->data[Y] + y0 * linesize,

               cur_buf->data[A] + y0 * linesize,

               linesize * h);

    } else {

        const int linesize = FFMIN(out_buf->linesize[Y], cur_buf->linesize[A]);

        int y;

        for (y = y0; y < (y0 + h); y++) {

            memcpy(out_buf->data[Y] + y * out_buf->linesize[Y],

                   cur_buf->data[A] + y * cur_buf->linesize[A],

                   linesize);

        }

    }

    return ff_draw_slice(inlink->dst->outputs[0], y0, h, slice_dir);

}


static int sad16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)

{

    int i;

    int s;

    const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0);

    vector unsigned char perm1, perm2, *pix1v, *pix2v;

    vector unsigned char t1, t2, t3,t4, t5;

    vector unsigned int sad;

    vector signed int sumdiffs;

    sad = (vector unsigned int)vec_splat_u32(0);

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

        /* Read potentially unaligned pixels into t1 and t2 */

        perm1 = vec_lvsl(0, pix1);

        pix1v = (vector unsigned char *) pix1;

        perm2 = vec_lvsl(0, pix2);

        pix2v = (vector unsigned char *) pix2;

        t1 = vec_perm(pix1v[0], pix1v[1], perm1);

        t2 = vec_perm(pix2v[0], pix2v[1], perm2);

        /* Calculate a sum of abs differences vector */

        t3 = vec_max(t1, t2);

        t4 = vec_min(t1, t2);

        t5 = vec_sub(t3, t4);

        /* Add each 4 pixel group together and put 4 results into sad */

        sad = vec_sum4s(t5, sad);

        pix1 += line_size;

        pix2 += line_size;

    }

    /* Sum up the four partial sums, and put the result into s */

    sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);

    sumdiffs = vec_splat(sumdiffs, 3);

    vec_ste(sumdiffs, 0, &s);

    return s;

}


void rgb8tobgr8(const uint8_t *src, uint8_t *dst, unsigned int src_size)

{

	unsigned i;

	unsigned num_pixels = src_size;

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

	{

	    unsigned b,g,r;

	    register uint8_t rgb;

	    rgb = src[i];

	    r = (rgb&0x07);

	    g = (rgb&0x38)>>3;

	    b = (rgb&0xC0)>>6;

	    dst[i] = ((b<<1)&0x07) | ((g&0x07)<<3) | ((r&0x03)<<6);

	}

}


static int net_vde_init(VLANState *vlan, const char *model,

                        const char *name, const char *sock,

                        int port, const char *group, int mode)

{

    VDEState *s;

    char *init_group = strlen(group) ? (char *)group : NULL;

    char *init_sock = strlen(sock) ? (char *)sock : NULL;

    struct vde_open_args args = {

        .port = port,

        .group = init_group,

        .mode = mode,

    };

    s = qemu_mallocz(sizeof(VDEState));

    s->vde = vde_open(init_sock, "QEMU", &args);

    if (!s->vde){

        free(s);

        return -1;

    }

    s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL, s);

    qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s);

    snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d",

             sock, vde_datafd(s->vde));

    return 0;

}


static int vorbis_parse_setup_hdr_residues(vorbis_context *vc){
    GetBitContext *gb=&vc->gb;
    uint_fast8_t i, j, k;
    vc->residue_count=get_bits(gb, 6)+1;
    vc->residues=av_mallocz(vc->residue_count * sizeof(vorbis_residue));
    AV_DEBUG(" There are %d residues. \n", vc->residue_count);
    for(i=0;i<vc->residue_count;++i) {
        vorbis_residue *res_setup=&vc->residues[i];
        uint_fast8_t cascade[64];
        uint_fast8_t high_bits;
        uint_fast8_t low_bits;
        res_setup->type=get_bits(gb, 16);
        AV_DEBUG(" %d. residue type %d \n", i, res_setup->type);
        res_setup->begin=get_bits(gb, 24);
        res_setup->end=get_bits(gb, 24);
        res_setup->partition_size=get_bits(gb, 24)+1;
        res_setup->classifications=get_bits(gb, 6)+1;
        res_setup->classbook=get_bits(gb, 8);
        if (res_setup->classbook>=vc->codebook_count) {
            av_log(vc->avccontext, AV_LOG_ERROR, "classbook value %d out of range. \n", res_setup->classbook);
        AV_DEBUG("    begin %d end %d part.size %d classif.s %d classbook %d \n", res_setup->begin, res_setup->end, res_setup->partition_size,
          res_setup->classifications, res_setup->classbook);
        for(j=0;j<res_setup->classifications;++j) {
            high_bits=0;
            low_bits=get_bits(gb, 3);
            if (get_bits1(gb)) {
                high_bits=get_bits(gb, 5);
            cascade[j]=(high_bits<<3)+low_bits;
            AV_DEBUG("     %d class casscade depth: %d \n", j, ilog(cascade[j]));
        res_setup->maxpass=0;
        for(j=0;j<res_setup->classifications;++j) {
            for(k=0;k<8;++k) {
                if (cascade[j]&(1<<k)) {
                    int bits=get_bits(gb, 8);
                    if (bits>=vc->codebook_count) {
                        av_log(vc->avccontext, AV_LOG_ERROR, "book value %d out of range. \n", bits);
                    res_setup->books[j][k]=bits;
                    AV_DEBUG("     %d class casscade depth %d book: %d \n", j, k, res_setup->books[j][k]);
                    if (k>res_setup->maxpass) {
                        res_setup->maxpass=k;
                } else {
                    res_setup->books[j][k]=-1;
    return 0;


static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt,

                                GetBitContext *gb, int block_size,

                                int width, int height, int x_pos, int y_pos,

                                int blk_idx)

{

    struct FlashSVContext *s = avctx->priv_data;

    uint8_t *line = s->tmpblock;

    int k;

    int ret = inflateReset(&s->zstream);

    if (ret != Z_OK) {

        av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);

        return AVERROR_UNKNOWN;

    }

    if (s->zlibprime_curr || s->zlibprime_prev) {

        ret = flashsv2_prime(s,

                             s->blocks[blk_idx].pos,

                             s->blocks[blk_idx].size);

        if (ret < 0)

            return ret;

    }

    s->zstream.next_in   = avpkt->data + get_bits_count(gb) / 8;

    s->zstream.avail_in  = block_size;

    s->zstream.next_out  = s->tmpblock;

    s->zstream.avail_out = s->block_size * 3;

    ret = inflate(&s->zstream, Z_FINISH);

    if (ret == Z_DATA_ERROR) {

        av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n");

        inflateSync(&s->zstream);

        ret = inflate(&s->zstream, Z_FINISH);

    }

    if (ret != Z_OK && ret != Z_STREAM_END) {

        //return -1;

    }

    if (s->is_keyframe) {

        s->blocks[blk_idx].pos  = s->keyframedata + (get_bits_count(gb) / 8);

        s->blocks[blk_idx].size = block_size;

    }

    y_pos += s->diff_start;

    if (!s->color_depth) {

        /* Flash Screen Video stores the image upside down, so copy

         * lines to destination in reverse order. */

        for (k = 1; k <= s->diff_height; k++) {

            memcpy(s->frame->data[0] + x_pos * 3 +

                   (s->image_height - y_pos - k) * s->frame->linesize[0],

                   line, width * 3);

            /* advance source pointer to next line */

            line += width * 3;

        }

    } else {

        /* hybrid 15-bit/palette mode */

        decode_hybrid(s->tmpblock, s->frame->data[0],

                      s->image_height - (y_pos + 1 + s->diff_height),

                      x_pos, s->diff_height, width,

                      s->frame->linesize[0], s->pal);

    }

    skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */

    return 0;

}


void breakpoint_handler(CPUX86State *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(env, EXCP01_DB);

            else

                cpu_resume_from_signal(env, NULL);

        }

    } else {

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

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

                if (bp->flags & BP_CPU) {

                    check_hw_breakpoints(env, 1);

                    raise_exception(env, EXCP01_DB);

                }

                break;

            }

    }

}


static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset)

{

    m5206_mbar_state *s = (m5206_mbar_state *)opaque;

    int width;

    offset &= 0x3ff;

    if (offset > 0x200) {

        hw_error("Bad MBAR read offset 0x%x", (int)offset);

    }

    width = m5206_mbar_width[offset >> 2];

    if (width < 4) {

        uint32_t val;

        val = m5206_mbar_readw(opaque, offset) << 16;

        val |= m5206_mbar_readw(opaque, offset + 2);

        return val;

    }

    return m5206_mbar_read(s, offset, 4);

}


static void test_qemu_strtoul_empty(void)

{

    const char *str = "";

    char f = 'X';

    const char *endptr = &f;

    unsigned long res = 999;

    int err;

    err = qemu_strtoul(str, &endptr, 0, &res);

    g_assert_cmpint(err, ==, 0);

    g_assert_cmpint(res, ==, 0);

    g_assert(endptr == str);

}


static void lm32_cpu_class_init(ObjectClass *oc, void *data)
{
    LM32CPUClass *lcc = LM32_CPU_CLASS(oc);
    CPUClass *cc = CPU_CLASS(oc);
    DeviceClass *dc = DEVICE_CLASS(oc);
    lcc->parent_realize = dc->realize;
    dc->realize = lm32_cpu_realizefn;
    lcc->parent_reset = cc->reset;
    cc->reset = lm32_cpu_reset;
    cc->class_by_name = lm32_cpu_class_by_name;
    cc->has_work = lm32_cpu_has_work;
    cc->do_interrupt = lm32_cpu_do_interrupt;
    cc->cpu_exec_interrupt = lm32_cpu_exec_interrupt;
    cc->dump_state = lm32_cpu_dump_state;
    cc->set_pc = lm32_cpu_set_pc;
    cc->gdb_read_register = lm32_cpu_gdb_read_register;
    cc->gdb_write_register = lm32_cpu_gdb_write_register;
#ifdef CONFIG_USER_ONLY
    cc->handle_mmu_fault = lm32_cpu_handle_mmu_fault;
#else
    cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug;
    cc->vmsd = &vmstate_lm32_cpu;
#endif
    cc->gdb_num_core_regs = 32 + 7;
    cc->gdb_stop_before_watchpoint = true;
    cc->debug_excp_handler = lm32_debug_excp_handler;
}


static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)

{

    /* send bitblit op to the vnc client */

    vnc_lock_output(vs);

    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);

    vnc_write_u8(vs, 0);

    vnc_write_u16(vs, 1); /* number of rects */

    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);

    vnc_write_u16(vs, src_x);

    vnc_write_u16(vs, src_y);

    vnc_unlock_output(vs);

    vnc_flush(vs);

}


static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize, int mb_xy, int mb_type, int mvy_limit, int first_vertical_edge_done, int chroma, int chroma444, int dir) {

    MpegEncContext * const s = &h->s;

    int edge;

    int chroma_qp_avg[2];

    const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy;

    const int mbm_type = dir == 0 ? h->left_type[LTOP] : h->top_type;

    // how often to recheck mv-based bS when iterating between edges

    static const uint8_t mask_edge_tab[2][8]={{0,3,3,3,1,1,1,1},

                                              {0,3,1,1,3,3,3,3}};

    const int mask_edge = mask_edge_tab[dir][(mb_type>>3)&7];

    const int edges = mask_edge== 3 && !(h->cbp&15) ? 1 : 4;

    // how often to recheck mv-based bS when iterating along each edge

    const int mask_par0 = mb_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir));

    if(mbm_type && !first_vertical_edge_done){

        if (FRAME_MBAFF && (dir == 1) && ((mb_y&1) == 0)

            && IS_INTERLACED(mbm_type&~mb_type)

            ) {

            // This is a special case in the norm where the filtering must

            // be done twice (one each of the field) even if we are in a

            // frame macroblock.

            //

            unsigned int tmp_linesize   = 2 *   linesize;

            unsigned int tmp_uvlinesize = 2 * uvlinesize;

            int mbn_xy = mb_xy - 2 * s->mb_stride;

            int j;

            for(j=0; j<2; j++, mbn_xy += s->mb_stride){

                DECLARE_ALIGNED(8, int16_t, bS)[4];

                int qp;

                if (IS_INTRA(mb_type | s->current_picture.f.mb_type[mbn_xy])) {

                    AV_WN64A(bS, 0x0003000300030003ULL);

                } else {

                    if (!CABAC && IS_8x8DCT(s->current_picture.f.mb_type[mbn_xy])) {

                        bS[0]= 1+((h->cbp_table[mbn_xy] & 0x4000)||h->non_zero_count_cache[scan8[0]+0]);

                        bS[1]= 1+((h->cbp_table[mbn_xy] & 0x4000)||h->non_zero_count_cache[scan8[0]+1]);

                        bS[2]= 1+((h->cbp_table[mbn_xy] & 0x8000)||h->non_zero_count_cache[scan8[0]+2]);

                        bS[3]= 1+((h->cbp_table[mbn_xy] & 0x8000)||h->non_zero_count_cache[scan8[0]+3]);

                    }else{

                    const uint8_t *mbn_nnz = h->non_zero_count[mbn_xy] + 3*4;

                    int i;

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

                        bS[i] = 1 + !!(h->non_zero_count_cache[scan8[0]+i] | mbn_nnz[i]);

                    }

                    }

                }

                // Do not use s->qscale as luma quantizer because it has not the same

                // value in IPCM macroblocks.

                qp = (s->current_picture.f.qscale_table[mb_xy] + s->current_picture.f.qscale_table[mbn_xy] + 1) >> 1;

                tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize);

                { int i; for (i = 0; i < 4; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); }

                filter_mb_edgeh( &img_y[j*linesize], tmp_linesize, bS, qp, h );

                chroma_qp_avg[0] = (h->chroma_qp[0] + get_chroma_qp(h, 0, s->current_picture.f.qscale_table[mbn_xy]) + 1) >> 1;

                chroma_qp_avg[1] = (h->chroma_qp[1] + get_chroma_qp(h, 1, s->current_picture.f.qscale_table[mbn_xy]) + 1) >> 1;

                if (chroma) {

                    if (chroma444) {

                        filter_mb_edgeh (&img_cb[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[0], h);

                        filter_mb_edgeh (&img_cr[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[1], h);

                    } else {

                        filter_mb_edgech(&img_cb[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[0], h);

                        filter_mb_edgech(&img_cr[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[1], h);

                    }

                }

            }

        }else{

            DECLARE_ALIGNED(8, int16_t, bS)[4];

            int qp;

            if( IS_INTRA(mb_type|mbm_type)) {

                AV_WN64A(bS, 0x0003000300030003ULL);

                if (   (!IS_INTERLACED(mb_type|mbm_type))

                    || ((FRAME_MBAFF || (s->picture_structure != PICT_FRAME)) && (dir == 0))

                )

                    AV_WN64A(bS, 0x0004000400040004ULL);

            } else {

                int i;

                int mv_done;

                if( dir && FRAME_MBAFF && IS_INTERLACED(mb_type ^ mbm_type)) {

                    AV_WN64A(bS, 0x0001000100010001ULL);

                    mv_done = 1;

                }

                else if( mask_par0 && ((mbm_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)))) ) {

                    int b_idx= 8 + 4;

                    int bn_idx= b_idx - (dir ? 8:1);

                    bS[0] = bS[1] = bS[2] = bS[3] = check_mv(h, 8 + 4, bn_idx, mvy_limit);

                    mv_done = 1;

                }

                else

                    mv_done = 0;

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

                    int x = dir == 0 ? 0 : i;

                    int y = dir == 0 ? i    : 0;

                    int b_idx= 8 + 4 + x + 8*y;

                    int bn_idx= b_idx - (dir ? 8:1);

                    if( h->non_zero_count_cache[b_idx] |

                        h->non_zero_count_cache[bn_idx] ) {

                        bS[i] = 2;

                    }

                    else if(!mv_done)

                    {

                        bS[i] = check_mv(h, b_idx, bn_idx, mvy_limit);

                    }

                }

            }

            /* Filter edge */

            // Do not use s->qscale as luma quantizer because it has not the same

            // value in IPCM macroblocks.

            if(bS[0]+bS[1]+bS[2]+bS[3]){

                qp = (s->current_picture.f.qscale_table[mb_xy] + s->current_picture.f.qscale_table[mbm_xy] + 1) >> 1;

                //tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp[0], s->current_picture.qscale_table[mbn_xy]);

                tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize);

                //{ int i; for (i = 0; i < 4; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); }

                chroma_qp_avg[0] = (h->chroma_qp[0] + get_chroma_qp(h, 0, s->current_picture.f.qscale_table[mbm_xy]) + 1) >> 1;

                chroma_qp_avg[1] = (h->chroma_qp[1] + get_chroma_qp(h, 1, s->current_picture.f.qscale_table[mbm_xy]) + 1) >> 1;

                if( dir == 0 ) {

                    filter_mb_edgev( &img_y[0], linesize, bS, qp, h );

                    if (chroma) {

                        if (chroma444) {

                            filter_mb_edgev ( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], h);

                            filter_mb_edgev ( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], h);

                        } else {

                            filter_mb_edgecv( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], h);

                            filter_mb_edgecv( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], h);

                        }

                    }

                } else {

                    filter_mb_edgeh( &img_y[0], linesize, bS, qp, h );

                    if (chroma) {

                        if (chroma444) {

                            filter_mb_edgeh ( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], h);

                            filter_mb_edgeh ( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], h);

                        } else {

                            filter_mb_edgech( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], h);

                            filter_mb_edgech( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], h);

                        }

                    }

                }

            }

        }

    }

    /* Calculate bS */

    for( edge = 1; edge < edges; edge++ ) {

        DECLARE_ALIGNED(8, int16_t, bS)[4];

        int qp;

        if( IS_8x8DCT(mb_type & (edge<<24)) ) // (edge&1) && IS_8x8DCT(mb_type)

            continue;

        if( IS_INTRA(mb_type)) {

            AV_WN64A(bS, 0x0003000300030003ULL);

        } else {

            int i;

            int mv_done;

            if( edge & mask_edge ) {

                AV_ZERO64(bS);

                mv_done = 1;

            }

            else if( mask_par0 ) {

                int b_idx= 8 + 4 + edge * (dir ? 8:1);

                int bn_idx= b_idx - (dir ? 8:1);

                bS[0] = bS[1] = bS[2] = bS[3] = check_mv(h, b_idx, bn_idx, mvy_limit);

                mv_done = 1;

            }

            else

                mv_done = 0;

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

                int x = dir == 0 ? edge : i;

                int y = dir == 0 ? i    : edge;

                int b_idx= 8 + 4 + x + 8*y;

                int bn_idx= b_idx - (dir ? 8:1);

                if( h->non_zero_count_cache[b_idx] |

                    h->non_zero_count_cache[bn_idx] ) {

                    bS[i] = 2;

                }

                else if(!mv_done)

                {

                    bS[i] = check_mv(h, b_idx, bn_idx, mvy_limit);

                }

            }

            if(bS[0]+bS[1]+bS[2]+bS[3] == 0)

                continue;

        }

        /* Filter edge */

        // Do not use s->qscale as luma quantizer because it has not the same

        // value in IPCM macroblocks.

        qp = s->current_picture.f.qscale_table[mb_xy];

        //tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp[0], s->current_picture.qscale_table[mbn_xy]);

        tprintf(s->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize);

        //{ int i; for (i = 0; i < 4; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); }

        if( dir == 0 ) {

            filter_mb_edgev( &img_y[4*edge << h->pixel_shift], linesize, bS, qp, h );

            if (chroma) {

                if (chroma444) {

                    filter_mb_edgev ( &img_cb[4*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[0], h);

                    filter_mb_edgev ( &img_cr[4*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[1], h);

                } else if( (edge&1) == 0 ) {

                    filter_mb_edgecv( &img_cb[2*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[0], h);

                    filter_mb_edgecv( &img_cr[2*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[1], h);

                }

            }

        } else {

            filter_mb_edgeh( &img_y[4*edge*linesize], linesize, bS, qp, h );

            if (chroma) {

                if (chroma444) {

                    filter_mb_edgeh ( &img_cb[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], h);

                    filter_mb_edgeh ( &img_cr[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], h);

                } else if( (edge&1) == 0 ) {

                    filter_mb_edgech( &img_cb[2*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], h);

                    filter_mb_edgech( &img_cr[2*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], h);

                }

            }

        }

    }

}


static int mov_read_close(AVFormatContext *s)

{

    MOVContext *mov = s->priv_data;

    int i, j;

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

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

        MOVStreamContext *sc = st->priv_data;

        av_freep(&sc->ctts_data);

        for (j = 0; j < sc->drefs_count; j++) {

            av_freep(&sc->drefs[j].path);

            av_freep(&sc->drefs[j].dir);

        }

        av_freep(&sc->drefs);

        if (sc->pb && sc->pb != s->pb)

            avio_close(sc->pb);

        av_freep(&sc->chunk_offsets);

        av_freep(&sc->stsc_data);

        av_freep(&sc->sample_sizes);

        av_freep(&sc->keyframes);

        av_freep(&sc->stts_data);

        av_freep(&sc->stps_data);

        av_freep(&sc->rap_group);

        av_freep(&sc->display_matrix);

    }

    if (mov->dv_demux) {

        avformat_free_context(mov->dv_fctx);

        mov->dv_fctx = NULL;

    }

    av_freep(&mov->trex_data);

    return 0;

}


static int color_request_frame(AVFilterLink *link)

{

    ColorContext *color = link->src->priv;

    AVFilterBufferRef *picref = ff_get_video_buffer(link, AV_PERM_WRITE, color->w, color->h);

    int ret;

    picref->video->pixel_aspect = (AVRational) {1, 1};

    picref->pts                 = color->pts++;

    picref->pos                 = -1;

    ret = ff_start_frame(link, avfilter_ref_buffer(picref, ~0));

    if (ret < 0)

        goto fail;

    ff_draw_rectangle(picref->data, picref->linesize,

                      color->line, color->line_step, color->hsub, color->vsub,

                      0, 0, color->w, color->h);

    ret = ff_draw_slice(link, 0, color->h, 1);

    if (ret < 0)

        goto fail;

    ret = ff_end_frame(link);

fail:

    avfilter_unref_buffer(picref);

    return ret;

}