int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter)

{

    int i;

    int usesVFilter, usesHFilter;

    int unscaled;

    SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};

    int srcW= c->srcW;

    int srcH= c->srcH;

    int dstW= c->dstW;

    int dstH= c->dstH;

    int dst_stride = FFALIGN(dstW * sizeof(int16_t) + 16, 16), dst_stride_px = dst_stride >> 1;

    int flags, cpu_flags;

    enum PixelFormat srcFormat= c->srcFormat;

    enum PixelFormat dstFormat= c->dstFormat;

    cpu_flags = av_get_cpu_flags();

    flags     = c->flags;

    emms_c();

    if (!rgb15to16) sws_rgb2rgb_init();

    unscaled = (srcW == dstW && srcH == dstH);

    if (!isSupportedIn(srcFormat)) {

        av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n", sws_format_name(srcFormat));

        return AVERROR(EINVAL);

    }

    if (!isSupportedOut(dstFormat)) {

        av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n", sws_format_name(dstFormat));

        return AVERROR(EINVAL);

    }

    i= flags & ( SWS_POINT

                |SWS_AREA

                |SWS_BILINEAR

                |SWS_FAST_BILINEAR

                |SWS_BICUBIC

                |SWS_X

                |SWS_GAUSS

                |SWS_LANCZOS

                |SWS_SINC

                |SWS_SPLINE

                |SWS_BICUBLIN);

    if(!i || (i & (i-1))) {

        av_log(c, AV_LOG_ERROR, "Exactly one scaler algorithm must be chosen\n");

        return AVERROR(EINVAL);

    }

    /* sanity check */

    if (srcW<4 || srcH<1 || dstW<8 || dstH<1) { //FIXME check if these are enough and try to lowwer them after fixing the relevant parts of the code

        av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",

               srcW, srcH, dstW, dstH);

        return AVERROR(EINVAL);

    }

    if (!dstFilter) dstFilter= &dummyFilter;

    if (!srcFilter) srcFilter= &dummyFilter;

    c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW;

    c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH;

    c->dstFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[dstFormat]);

    c->srcFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[srcFormat]);

    c->vRounder= 4* 0x0001000100010001ULL;

    usesVFilter = (srcFilter->lumV && srcFilter->lumV->length>1) ||

                  (srcFilter->chrV && srcFilter->chrV->length>1) ||

                  (dstFilter->lumV && dstFilter->lumV->length>1) ||

                  (dstFilter->chrV && dstFilter->chrV->length>1);

    usesHFilter = (srcFilter->lumH && srcFilter->lumH->length>1) ||

                  (srcFilter->chrH && srcFilter->chrH->length>1) ||

                  (dstFilter->lumH && dstFilter->lumH->length>1) ||

                  (dstFilter->chrH && dstFilter->chrH->length>1);

    getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);

    getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);

    // reuse chroma for 2 pixels RGB/BGR unless user wants full chroma interpolation

    if (flags & SWS_FULL_CHR_H_INT &&

        dstFormat != PIX_FMT_RGBA &&

        dstFormat != PIX_FMT_ARGB &&

        dstFormat != PIX_FMT_BGRA &&

        dstFormat != PIX_FMT_ABGR &&

        dstFormat != PIX_FMT_RGB24 &&

        dstFormat != PIX_FMT_BGR24) {

        av_log(c, AV_LOG_ERROR,

               "full chroma interpolation for destination format '%s' not yet implemented\n",

               sws_format_name(dstFormat));

        flags &= ~SWS_FULL_CHR_H_INT;

        c->flags = flags;

    }

    if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1;

    // drop some chroma lines if the user wants it

    c->vChrDrop= (flags&SWS_SRC_V_CHR_DROP_MASK)>>SWS_SRC_V_CHR_DROP_SHIFT;

    c->chrSrcVSubSample+= c->vChrDrop;

    // drop every other pixel for chroma calculation unless user wants full chroma

    if (isAnyRGB(srcFormat) && !(flags&SWS_FULL_CHR_H_INP)

      && srcFormat!=PIX_FMT_RGB8      && srcFormat!=PIX_FMT_BGR8

      && srcFormat!=PIX_FMT_RGB4      && srcFormat!=PIX_FMT_BGR4

      && srcFormat!=PIX_FMT_RGB4_BYTE && srcFormat!=PIX_FMT_BGR4_BYTE

      && ((dstW>>c->chrDstHSubSample) <= (srcW>>1) || (flags&SWS_FAST_BILINEAR)))

        c->chrSrcHSubSample=1;

    // Note the -((-x)>>y) is so that we always round toward +inf.

    c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample);

    c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample);

    c->chrDstW= -((-dstW) >> c->chrDstHSubSample);

    c->chrDstH= -((-dstH) >> c->chrDstVSubSample);

    /* unscaled special cases */

    if (unscaled && !usesHFilter && !usesVFilter && (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) {

        ff_get_unscaled_swscale(c);

        if (c->swScale) {

            if (flags&SWS_PRINT_INFO)

                av_log(c, AV_LOG_INFO, "using unscaled %s -> %s special converter\n",

                       sws_format_name(srcFormat), sws_format_name(dstFormat));

            return 0;

        }

    }

    c->scalingBpp = FFMAX(av_pix_fmt_descriptors[srcFormat].comp[0].depth_minus1,

                          av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1) >= 8 ? 16 : 8;

    if (c->scalingBpp == 16)

        dst_stride <<= 1;

    FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW, 16) * 2 * c->scalingBpp >> 3, fail);

    if (HAVE_MMX2 && cpu_flags & AV_CPU_FLAG_MMX2 && c->scalingBpp == 8) {

        c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0;

        if (!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (flags&SWS_FAST_BILINEAR)) {

            if (flags&SWS_PRINT_INFO)

                av_log(c, AV_LOG_INFO, "output width is not a multiple of 32 -> no MMX2 scaler\n");

        }

        if (usesHFilter) c->canMMX2BeUsed=0;

    }

    else

        c->canMMX2BeUsed=0;

    c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW;

    c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH;

    // match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src to pixel n-2 of dst

    // but only for the FAST_BILINEAR mode otherwise do correct scaling

    // n-2 is the last chrominance sample available

    // this is not perfect, but no one should notice the difference, the more correct variant

    // would be like the vertical one, but that would require some special code for the

    // first and last pixel

    if (flags&SWS_FAST_BILINEAR) {

        if (c->canMMX2BeUsed) {

            c->lumXInc+= 20;

            c->chrXInc+= 20;

        }

        //we don't use the x86 asm scaler if MMX is available

        else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) {

            c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20;

            c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20;

        }

    }

    /* precalculate horizontal scaler filter coefficients */

    {

#if HAVE_MMX2

// can't downscale !!!

        if (c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR)) {

            c->lumMmx2FilterCodeSize = initMMX2HScaler(      dstW, c->lumXInc, NULL, NULL, NULL, 8);

            c->chrMmx2FilterCodeSize = initMMX2HScaler(c->chrDstW, c->chrXInc, NULL, NULL, NULL, 4);

#ifdef MAP_ANONYMOUS

            c->lumMmx2FilterCode = mmap(NULL, c->lumMmx2FilterCodeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

            c->chrMmx2FilterCode = mmap(NULL, c->chrMmx2FilterCodeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

#elif HAVE_VIRTUALALLOC

            c->lumMmx2FilterCode = VirtualAlloc(NULL, c->lumMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

            c->chrMmx2FilterCode = VirtualAlloc(NULL, c->chrMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

#else

            c->lumMmx2FilterCode = av_malloc(c->lumMmx2FilterCodeSize);

            c->chrMmx2FilterCode = av_malloc(c->chrMmx2FilterCodeSize);

#endif

            if (!c->lumMmx2FilterCode || !c->chrMmx2FilterCode)

                return AVERROR(ENOMEM);

            FF_ALLOCZ_OR_GOTO(c, c->hLumFilter   , (dstW        /8+8)*sizeof(int16_t), fail);

            FF_ALLOCZ_OR_GOTO(c, c->hChrFilter   , (c->chrDstW  /4+8)*sizeof(int16_t), fail);

            FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW      /2/8+8)*sizeof(int32_t), fail);

            FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW/2/4+8)*sizeof(int32_t), fail);

            initMMX2HScaler(      dstW, c->lumXInc, c->lumMmx2FilterCode, c->hLumFilter, c->hLumFilterPos, 8);

            initMMX2HScaler(c->chrDstW, c->chrXInc, c->chrMmx2FilterCode, c->hChrFilter, c->hChrFilterPos, 4);

#ifdef MAP_ANONYMOUS

            mprotect(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize, PROT_EXEC | PROT_READ);

            mprotect(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize, PROT_EXEC | PROT_READ);

#endif

        } else

#endif /* HAVE_MMX2 */

        {

            const int filterAlign=

                (HAVE_MMX     && cpu_flags & AV_CPU_FLAG_MMX) ? 4 :

                (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :

                1;

            if (initFilter(&c->hLumFilter, &c->hLumFilterPos, &c->hLumFilterSize, c->lumXInc,

                           srcW      ,       dstW, filterAlign, 1<<14,

                           (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC)  : flags, cpu_flags,

                           srcFilter->lumH, dstFilter->lumH, c->param) < 0)

                goto fail;

            if (initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc,

                           c->chrSrcW, c->chrDstW, filterAlign, 1<<14,

                           (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags, cpu_flags,

                           srcFilter->chrH, dstFilter->chrH, c->param) < 0)

                goto fail;

        }

    } // initialize horizontal stuff

    /* precalculate vertical scaler filter coefficients */

    {

        const int filterAlign=

            (HAVE_MMX     && cpu_flags & AV_CPU_FLAG_MMX) && (flags & SWS_ACCURATE_RND) ? 2 :

            (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :

            1;

        if (initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize, c->lumYInc,

                       srcH      ,        dstH, filterAlign, (1<<12),

                       (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC)  : flags, cpu_flags,

                       srcFilter->lumV, dstFilter->lumV, c->param) < 0)

            goto fail;

        if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize, c->chrYInc,

                       c->chrSrcH, c->chrDstH, filterAlign, (1<<12),

                       (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags, cpu_flags,

                       srcFilter->chrV, dstFilter->chrV, c->param) < 0)

            goto fail;

#if HAVE_ALTIVEC

        FF_ALLOC_OR_GOTO(c, c->vYCoeffsBank, sizeof (vector signed short)*c->vLumFilterSize*c->dstH, fail);

        FF_ALLOC_OR_GOTO(c, c->vCCoeffsBank, sizeof (vector signed short)*c->vChrFilterSize*c->chrDstH, fail);

        for (i=0;i<c->vLumFilterSize*c->dstH;i++) {

            int j;

            short *p = (short *)&c->vYCoeffsBank[i];

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

                p[j] = c->vLumFilter[i];

        }

        for (i=0;i<c->vChrFilterSize*c->chrDstH;i++) {

            int j;

            short *p = (short *)&c->vCCoeffsBank[i];

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

                p[j] = c->vChrFilter[i];

        }

#endif

    }

    // calculate buffer sizes so that they won't run out while handling these damn slices

    c->vLumBufSize= c->vLumFilterSize;

    c->vChrBufSize= c->vChrFilterSize;

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

        int chrI= i*c->chrDstH / dstH;

        int nextSlice= FFMAX(c->vLumFilterPos[i   ] + c->vLumFilterSize - 1,

                           ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<c->chrSrcVSubSample));

        nextSlice>>= c->chrSrcVSubSample;

        nextSlice<<= c->chrSrcVSubSample;

        if (c->vLumFilterPos[i   ] + c->vLumBufSize < nextSlice)

            c->vLumBufSize= nextSlice - c->vLumFilterPos[i];

        if (c->vChrFilterPos[chrI] + c->vChrBufSize < (nextSlice>>c->chrSrcVSubSample))

            c->vChrBufSize= (nextSlice>>c->chrSrcVSubSample) - c->vChrFilterPos[chrI];

    }

    // allocate pixbufs (we use dynamic allocation because otherwise we would need to

    // allocate several megabytes to handle all possible cases)

    FF_ALLOC_OR_GOTO(c, c->lumPixBuf, c->vLumBufSize*2*sizeof(int16_t*), fail);

    FF_ALLOC_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize*2*sizeof(int16_t*), fail);

    FF_ALLOC_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize*2*sizeof(int16_t*), fail);

    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))

        FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize*2*sizeof(int16_t*), fail);

    //Note we need at least one pixel more at the end because of the MMX code (just in case someone wanna replace the 4000/8000)

    /* align at 16 bytes for AltiVec */

    for (i=0; i<c->vLumBufSize; i++) {

        FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i+c->vLumBufSize], dst_stride+1, fail);

        c->lumPixBuf[i] = c->lumPixBuf[i+c->vLumBufSize];

    }

    c->uv_off_px   = dst_stride_px;

    c->uv_off_byte = dst_stride;

    for (i=0; i<c->vChrBufSize; i++) {

        FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i+c->vChrBufSize], dst_stride*2+1, fail);

        c->chrUPixBuf[i] = c->chrUPixBuf[i+c->vChrBufSize];

        c->chrVPixBuf[i] = c->chrVPixBuf[i+c->vChrBufSize] = c->chrUPixBuf[i] + (dst_stride >> 1);

    }

    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)

        for (i=0; i<c->vLumBufSize; i++) {

            FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf[i+c->vLumBufSize], dst_stride+1, fail);

            c->alpPixBuf[i] = c->alpPixBuf[i+c->vLumBufSize];

        }

    //try to avoid drawing green stuff between the right end and the stride end

    for (i=0; i<c->vChrBufSize; i++)

        memset(c->chrUPixBuf[i], 64, dst_stride*2+1);

    assert(c->chrDstH <= dstH);

    if (flags&SWS_PRINT_INFO) {

        if      (flags&SWS_FAST_BILINEAR) av_log(c, AV_LOG_INFO, "FAST_BILINEAR scaler, ");

        else if (flags&SWS_BILINEAR)      av_log(c, AV_LOG_INFO, "BILINEAR scaler, ");

        else if (flags&SWS_BICUBIC)       av_log(c, AV_LOG_INFO, "BICUBIC scaler, ");

        else if (flags&SWS_X)             av_log(c, AV_LOG_INFO, "Experimental scaler, ");

        else if (flags&SWS_POINT)         av_log(c, AV_LOG_INFO, "Nearest Neighbor / POINT scaler, ");

        else if (flags&SWS_AREA)          av_log(c, AV_LOG_INFO, "Area Averaging scaler, ");

        else if (flags&SWS_BICUBLIN)      av_log(c, AV_LOG_INFO, "luma BICUBIC / chroma BILINEAR scaler, ");

        else if (flags&SWS_GAUSS)         av_log(c, AV_LOG_INFO, "Gaussian scaler, ");

        else if (flags&SWS_SINC)          av_log(c, AV_LOG_INFO, "Sinc scaler, ");

        else if (flags&SWS_LANCZOS)       av_log(c, AV_LOG_INFO, "Lanczos scaler, ");

        else if (flags&SWS_SPLINE)        av_log(c, AV_LOG_INFO, "Bicubic spline scaler, ");

        else                              av_log(c, AV_LOG_INFO, "ehh flags invalid?! ");

        av_log(c, AV_LOG_INFO, "from %s to %s%s ",

               sws_format_name(srcFormat),

#ifdef DITHER1XBPP

               dstFormat == PIX_FMT_BGR555 || dstFormat == PIX_FMT_BGR565 ||

               dstFormat == PIX_FMT_RGB444BE || dstFormat == PIX_FMT_RGB444LE ||

               dstFormat == PIX_FMT_BGR444BE || dstFormat == PIX_FMT_BGR444LE ? "dithered " : "",

#else

               "",

#endif

               sws_format_name(dstFormat));

        if      (HAVE_MMX2     && cpu_flags & AV_CPU_FLAG_MMX2)    av_log(c, AV_LOG_INFO, "using MMX2\n");

        else if (HAVE_AMD3DNOW && cpu_flags & AV_CPU_FLAG_3DNOW)   av_log(c, AV_LOG_INFO, "using 3DNOW\n");

        else if (HAVE_MMX      && cpu_flags & AV_CPU_FLAG_MMX)     av_log(c, AV_LOG_INFO, "using MMX\n");

        else if (HAVE_ALTIVEC  && cpu_flags & AV_CPU_FLAG_ALTIVEC) av_log(c, AV_LOG_INFO, "using AltiVec\n");

        else                                   av_log(c, AV_LOG_INFO, "using C\n");

        if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) {

            if (c->canMMX2BeUsed && (flags&SWS_FAST_BILINEAR))

                av_log(c, AV_LOG_VERBOSE, "using FAST_BILINEAR MMX2 scaler for horizontal scaling\n");

            else {

                if (c->hLumFilterSize==4)

                    av_log(c, AV_LOG_VERBOSE, "using 4-tap MMX scaler for horizontal luminance scaling\n");

                else if (c->hLumFilterSize==8)

                    av_log(c, AV_LOG_VERBOSE, "using 8-tap MMX scaler for horizontal luminance scaling\n");

                else

                    av_log(c, AV_LOG_VERBOSE, "using n-tap MMX scaler for horizontal luminance scaling\n");

                if (c->hChrFilterSize==4)

                    av_log(c, AV_LOG_VERBOSE, "using 4-tap MMX scaler for horizontal chrominance scaling\n");

                else if (c->hChrFilterSize==8)

                    av_log(c, AV_LOG_VERBOSE, "using 8-tap MMX scaler for horizontal chrominance scaling\n");

                else

                    av_log(c, AV_LOG_VERBOSE, "using n-tap MMX scaler for horizontal chrominance scaling\n");

            }

        } else {

#if HAVE_MMX

            av_log(c, AV_LOG_VERBOSE, "using x86 asm scaler for horizontal scaling\n");

#else

            if (flags & SWS_FAST_BILINEAR)

                av_log(c, AV_LOG_VERBOSE, "using FAST_BILINEAR C scaler for horizontal scaling\n");

            else

                av_log(c, AV_LOG_VERBOSE, "using C scaler for horizontal scaling\n");

#endif

        }

        if (isPlanarYUV(dstFormat)) {

            if (c->vLumFilterSize==1)

                av_log(c, AV_LOG_VERBOSE, "using 1-tap %s \"scaler\" for vertical scaling (YV12 like)\n",

                       (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

            else

                av_log(c, AV_LOG_VERBOSE, "using n-tap %s scaler for vertical scaling (YV12 like)\n",

                       (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

        } else {

            if (c->vLumFilterSize==1 && c->vChrFilterSize==2)

                av_log(c, AV_LOG_VERBOSE, "using 1-tap %s \"scaler\" for vertical luminance scaling (BGR)\n"

                       "      2-tap scaler for vertical chrominance scaling (BGR)\n",

                       (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

            else if (c->vLumFilterSize==2 && c->vChrFilterSize==2)

                av_log(c, AV_LOG_VERBOSE, "using 2-tap linear %s scaler for vertical scaling (BGR)\n",

                       (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

            else

                av_log(c, AV_LOG_VERBOSE, "using n-tap %s scaler for vertical scaling (BGR)\n",

                       (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

        }

        if (dstFormat==PIX_FMT_BGR24)

            av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR24 converter\n",

                   (HAVE_MMX2 && cpu_flags & AV_CPU_FLAG_MMX2) ? "MMX2" :

                   ((HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C"));

        else if (dstFormat==PIX_FMT_RGB32)

            av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR32 converter\n",

                   (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

        else if (dstFormat==PIX_FMT_BGR565)

            av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR16 converter\n",

                   (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

        else if (dstFormat==PIX_FMT_BGR555)

            av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR15 converter\n",

                   (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

        else if (dstFormat == PIX_FMT_RGB444BE || dstFormat == PIX_FMT_RGB444LE ||

                 dstFormat == PIX_FMT_BGR444BE || dstFormat == PIX_FMT_BGR444LE)

            av_log(c, AV_LOG_VERBOSE, "using %s YV12->BGR12 converter\n",

                   (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? "MMX" : "C");

        av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);

        av_log(c, AV_LOG_DEBUG, "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",

               c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);

        av_log(c, AV_LOG_DEBUG, "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",

               c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH, c->chrXInc, c->chrYInc);

    }

    c->swScale= ff_getSwsFunc(c);

    return 0;

fail: //FIXME replace things by appropriate error codes

    return -1;

}


static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)

 {

     PowerPCCPU *cpu = ppc_env_get_cpu(env);

     CPUState *cs = CPU(cpu);

    if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&

        !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, pvinfo)) {

        return 0;

    }

    return 1;

}


static void vncws_tls_handshake_io(void *opaque)

{

    struct VncState *vs = (struct VncState *)opaque;

    VNC_DEBUG("Handshake IO continue\n");

    vncws_start_tls_handshake(vs);

}


static void pause_all_vcpus(void)

{

    CPUState *penv = first_cpu;

    while (penv) {

        penv->stop = 1;

        qemu_thread_signal(penv->thread, SIGUSR1);

        qemu_cpu_kick(penv);

        penv = (CPUState *)penv->next_cpu;

    }

    while (!all_vcpus_paused()) {

        qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);

        penv = first_cpu;

        while (penv) {

            qemu_thread_signal(penv->thread, SIGUSR1);

            penv = (CPUState *)penv->next_cpu;

        }

    }

}


static void pnv_icp_realize(DeviceState *dev, Error **errp)

{

    PnvICPState *icp = PNV_ICP(dev);

    memory_region_init_io(&icp->mmio, OBJECT(dev), &pnv_icp_ops,

                          icp, "icp-thread", 0x1000);

}


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

{

    DeviceClass *k = DEVICE_CLASS(klass);

    k->bus_type = TYPE_USB_BUS;

    k->init     = usb_qdev_init;

    k->unplug   = qdev_simple_unplug_cb;

    k->exit     = usb_qdev_exit;

    k->props    = usb_props;

}


static void qmp_output_type_bool(Visitor *v, const char *name, bool *obj,

                                 Error **errp)

{

    QmpOutputVisitor *qov = to_qov(v);

    qmp_output_add(qov, name, qbool_from_bool(*obj));

}


static unsigned int * create_elf_tables(char *p, int argc, int envc,

                                        struct elfhdr * exec,

                                        unsigned long load_addr,

                                        unsigned long load_bias,

                                        unsigned long interp_load_addr, int ibcs,

                                        struct image_info *info)

{

        target_ulong *argv, *envp;

        target_ulong *sp, *csp;

	/*

	 * Force 16 byte _final_ alignment here for generality.

	 */

        sp = (unsigned int *) (~15UL & (unsigned long) p);

        csp = sp;

        csp -= (DLINFO_ITEMS + 1) * 2;

#ifdef DLINFO_ARCH_ITEMS

	csp -= DLINFO_ARCH_ITEMS*2;

#endif

        csp -= envc+1;

        csp -= argc+1;

	csp -= (!ibcs ? 3 : 1);	/* argc itself */

        if ((unsigned long)csp & 15UL)

            sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);

#define NEW_AUX_ENT(nr, id, val) \

          put_user (tswapl(id), sp + (nr * 2)); \

          put_user (tswapl(val), sp + (nr * 2 + 1))

        sp -= 2;

        NEW_AUX_ENT (0, AT_NULL, 0);

	sp -= DLINFO_ITEMS*2;

        NEW_AUX_ENT( 0, AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));

        NEW_AUX_ENT( 1, AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));

        NEW_AUX_ENT( 2, AT_PHNUM, (target_ulong)(exec->e_phnum));

        NEW_AUX_ENT( 3, AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));

        NEW_AUX_ENT( 4, AT_BASE, (target_ulong)(interp_load_addr));

        NEW_AUX_ENT( 5, AT_FLAGS, (target_ulong)0);

        NEW_AUX_ENT( 6, AT_ENTRY, load_bias + exec->e_entry);

        NEW_AUX_ENT( 7, AT_UID, (target_ulong) getuid());

        NEW_AUX_ENT( 8, AT_EUID, (target_ulong) geteuid());

        NEW_AUX_ENT( 9, AT_GID, (target_ulong) getgid());

        NEW_AUX_ENT(11, AT_EGID, (target_ulong) getegid());

#ifdef ARCH_DLINFO

	/*

	 * ARCH_DLINFO must come last so platform specific code can enforce

	 * special alignment requirements on the AUXV if necessary (eg. PPC).

	 */

        ARCH_DLINFO;

#endif

#undef NEW_AUX_ENT

        sp -= envc+1;

        envp = sp;

        sp -= argc+1;

        argv = sp;

        if (!ibcs) {

                put_user(tswapl((target_ulong)envp),--sp);

                put_user(tswapl((target_ulong)argv),--sp);

        }

        put_user(tswapl(argc),--sp);

        info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);

        while (argc-->0) {

                put_user(tswapl((target_ulong)p),argv++);

                while (get_user(p++)) /* nothing */ ;

        }

        put_user(0,argv);

        info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);

        while (envc-->0) {

                put_user(tswapl((target_ulong)p),envp++);

                while (get_user(p++)) /* nothing */ ;

        }

        put_user(0,envp);

        info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);

        return sp;

}


static void assigned_dev_msix_mmio_write(void *opaque, target_phys_addr_t addr,

                                         uint64_t val, unsigned size)

{

    AssignedDevice *adev = opaque;

    PCIDevice *pdev = &adev->dev;

    uint16_t ctrl;

    MSIXTableEntry orig;

    int i = addr >> 4;

    if (i >= adev->msix_max) {

        return; /* Drop write */

    }

    ctrl = pci_get_word(pdev->config + pdev->msix_cap + PCI_MSIX_FLAGS);

    DEBUG("write to MSI-X table offset 0x%lx, val 0x%lx\n", addr, val);

    if (ctrl & PCI_MSIX_FLAGS_ENABLE) {

        orig = adev->msix_table[i];

    }

    memcpy((uint8_t *)adev->msix_table + addr, &val, size);

    if (ctrl & PCI_MSIX_FLAGS_ENABLE) {

        MSIXTableEntry *entry = &adev->msix_table[i];

        if (!assigned_dev_msix_masked(&orig) &&

            assigned_dev_msix_masked(entry)) {

            /*

             * Vector masked, disable it

             *

             * XXX It's not clear if we can or should actually attempt

             * to mask or disable the interrupt.  KVM doesn't have

             * support for pending bits and kvm_assign_set_msix_entry

             * doesn't modify the device hardware mask.  Interrupts

             * while masked are simply not injected to the guest, so

             * are lost.  Can we get away with always injecting an

             * interrupt on unmask?

             */

        } else if (assigned_dev_msix_masked(&orig) &&

                   !assigned_dev_msix_masked(entry)) {

            /* Vector unmasked */

            if (i >= adev->msi_virq_nr || adev->msi_virq[i] < 0) {

                /* Previously unassigned vector, start from scratch */

                assigned_dev_update_msix(pdev);

                return;

            } else {

                /* Update an existing, previously masked vector */

                MSIMessage msg;

                int ret;

                msg.address = entry->addr_lo |

                    ((uint64_t)entry->addr_hi << 32);

                msg.data = entry->data;

                ret = kvm_irqchip_update_msi_route(kvm_state,

                                                   adev->msi_virq[i], msg);

                if (ret) {

                    error_report("Error updating irq routing entry (%d)", ret);

                }

            }

        }

    }

}


static void test_cancel(void)

{

    WorkerTestData data[100];

    int num_canceled;

    int i;

    /* Start more work items than there will be threads, to ensure

     * the pool is full.

     */

    test_submit_many();

    /* Start long running jobs, to ensure we can cancel some.  */

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

        data[i].n = 0;

        data[i].ret = -EINPROGRESS;

        data[i].aiocb = thread_pool_submit_aio(long_cb, &data[i],

                                               done_cb, &data[i]);

    }

    /* Starting the threads may be left to a bottom half.  Let it

     * run, but do not waste too much time...

     */

    active = 100;

    qemu_aio_wait_nonblocking();

    /* Wait some time for the threads to start, with some sanity

     * testing on the behavior of the scheduler...

     */

    g_assert_cmpint(active, ==, 100);

    g_usleep(1000000);

    g_assert_cmpint(active, >, 50);

    /* Cancel the jobs that haven't been started yet.  */

    num_canceled = 0;

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

        if (__sync_val_compare_and_swap(&data[i].n, 0, 3) == 0) {

            data[i].ret = -ECANCELED;

            bdrv_aio_cancel(data[i].aiocb);

            active--;

            num_canceled++;

        }

    }

    g_assert_cmpint(active, >, 0);

    g_assert_cmpint(num_canceled, <, 100);

    /* Canceling the others will be a blocking operation.  */

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

        if (data[i].n != 3) {

            bdrv_aio_cancel(data[i].aiocb);

        }

    }

    /* Finish execution and execute any remaining callbacks.  */

    qemu_aio_wait_all();

    g_assert_cmpint(active, ==, 0);

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

        if (data[i].n == 3) {

            g_assert_cmpint(data[i].ret, ==, -ECANCELED);

            g_assert(data[i].aiocb != NULL);

        } else {

            g_assert_cmpint(data[i].n, ==, 2);

            g_assert_cmpint(data[i].ret, ==, 0);

            g_assert(data[i].aiocb == NULL);

        }

    }

}


int qemu_paio_write(struct qemu_paiocb *aiocb)

{

    return qemu_paio_submit(aiocb, QEMU_PAIO_WRITE);

}


static ssize_t v9fs_synth_llistxattr(FsContext *ctx, V9fsPath *path,

                                     void *value, size_t size)

{

    errno = ENOTSUP;

    return -1;

}


static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs,

                                 Error **errp)

{

    char *p, *buf;

    char *name;

    char *value;

    Error *local_err = NULL;

    int ret = 0;

    buf = g_strdup(keypairs);

    p = buf;

    while (p) {

        name = qemu_rbd_next_tok(RBD_MAX_CONF_NAME_SIZE, p,

                                 '=', "conf option name", &p, &local_err);

        if (local_err) {

            break;

        }

        if (!p) {

            error_setg(errp, "conf option %s has no value", name);

            ret = -EINVAL;

            break;

        }

        value = qemu_rbd_next_tok(RBD_MAX_CONF_VAL_SIZE, p,

                                  ':', "conf option value", &p, &local_err);

        if (local_err) {

            break;

        }

        ret = rados_conf_set(cluster, name, value);

        if (ret < 0) {

            error_setg_errno(errp, -ret, "invalid conf option %s", name);

            ret = -EINVAL;

            break;

        }

    }

    if (local_err) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

    }

    g_free(buf);

    return ret;

}


static void spapr_phb_remove_pci_device_cb(DeviceState *dev, void *opaque)

{

    /* some version guests do not wait for completion of a device

     * cleanup (generally done asynchronously by the kernel) before

     * signaling to QEMU that the device is safe, but instead sleep

     * for some 'safe' period of time. unfortunately on a busy host

     * this sleep isn't guaranteed to be long enough, resulting in

     * bad things like IRQ lines being left asserted during final

     * device removal. to deal with this we call reset just prior

     * to finalizing the device, which will put the device back into

     * an 'idle' state, as the device cleanup code expects.

     */

    pci_device_reset(PCI_DEVICE(dev));

    object_unparent(OBJECT(dev));

}


static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *ap)

{

    QDict *dict = NULL;

    QObject *token, *peek;

    QList *working = qlist_copy(*tokens);

    token = qlist_pop(working);

    if (token == NULL) {

        goto out;

    }

    if (!token_is_operator(token, '{')) {

        goto out;

    }

    qobject_decref(token);

    token = NULL;

    dict = qdict_new();

    peek = qlist_peek(working);

    if (peek == NULL) {

        parse_error(ctxt, NULL, "premature EOI");

        goto out;

    }

    if (!token_is_operator(peek, '}')) {

        if (parse_pair(ctxt, dict, &working, ap) == -1) {

            goto out;

        }

        token = qlist_pop(working);

        if (token == NULL) {

            parse_error(ctxt, NULL, "premature EOI");

            goto out;

        }

        while (!token_is_operator(token, '}')) {

            if (!token_is_operator(token, ',')) {

                parse_error(ctxt, token, "expected separator in dict");

                goto out;

            }

            qobject_decref(token);

            token = NULL;

            if (parse_pair(ctxt, dict, &working, ap) == -1) {

                goto out;

            }

            token = qlist_pop(working);

            if (token == NULL) {

                parse_error(ctxt, NULL, "premature EOI");

                goto out;

            }

        }

        qobject_decref(token);

        token = NULL;

    } else {

        token = qlist_pop(working);

        qobject_decref(token);

        token = NULL;

    }

    QDECREF(*tokens);

    *tokens = working;

    return QOBJECT(dict);

out:

    qobject_decref(token);

    QDECREF(working);

    QDECREF(dict);

    return NULL;

}


static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,

        int64_t sector_num, int nb_sectors, int *pnum)

{

    BDRVQcow2State *s = bs->opaque;

    uint64_t cluster_offset;

    int index_in_cluster, ret;

    int64_t status = 0;

    *pnum = nb_sectors;

    qemu_co_mutex_lock(&s->lock);

    ret = qcow2_get_cluster_offset(bs, sector_num << 9, pnum, &cluster_offset);

    qemu_co_mutex_unlock(&s->lock);

    if (ret < 0) {

        return ret;

    }

    if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED &&

        !s->cipher) {

        index_in_cluster = sector_num & (s->cluster_sectors - 1);

        cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);

        status |= BDRV_BLOCK_OFFSET_VALID | cluster_offset;

    }

    if (ret == QCOW2_CLUSTER_ZERO) {

        status |= BDRV_BLOCK_ZERO;

    } else if (ret != QCOW2_CLUSTER_UNALLOCATED) {

        status |= BDRV_BLOCK_DATA;

    }

    return status;

}


int avpriv_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le,

                           int depth, AVDictionary **metadata)

{

    int i, ret;

    int entries;

    entries = ff_tget_short(gbytes, le);

    if (bytestream2_get_bytes_left(gbytes) < entries * 12) {

        return AVERROR_INVALIDDATA;

    }

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

        if ((ret = exif_decode_tag(logctx, gbytes, le, depth, metadata)) < 0) {

            return ret;

        }

    }

    // return next IDF offset or 0x000000000 or a value < 0 for failure

    return ff_tget_long(gbytes, le);

}


static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory,

                target_phys_addr_t base,

                qemu_irq *irq, omap_clk clk)

{

    struct omap_rtc_s *s = (struct omap_rtc_s *)

            g_malloc0(sizeof(struct omap_rtc_s));

    s->irq = irq[0];

    s->alarm = irq[1];

    s->clk = qemu_new_timer_ms(rt_clock, omap_rtc_tick, s);

    omap_rtc_reset(s);

    memory_region_init_io(&s->iomem, &omap_rtc_ops, s,

                          "omap-rtc", 0x800);

    memory_region_add_subregion(system_memory, base, &s->iomem);

    return s;

}


static inline void patch_reloc(tcg_insn_unit *code_ptr, int type,

                               intptr_t value, intptr_t addend)

{

    assert(addend == 0);

    switch (type) {

    case R_AARCH64_JUMP26:

    case R_AARCH64_CALL26:

        reloc_pc26(code_ptr, (tcg_insn_unit *)value);

        break;

    case R_AARCH64_CONDBR19:

        reloc_pc19(code_ptr, (tcg_insn_unit *)value);

        break;

    default:

        tcg_abort();

    }

}


static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)

{

    int rd = extract32(insn, 0, 5);

    int cmode = extract32(insn, 12, 4);

    int cmode_3_1 = extract32(cmode, 1, 3);

    int cmode_0 = extract32(cmode, 0, 1);

    int o2 = extract32(insn, 11, 1);

    uint64_t abcdefgh = extract32(insn, 5, 5) | (extract32(insn, 16, 3) << 5);

    bool is_neg = extract32(insn, 29, 1);

    bool is_q = extract32(insn, 30, 1);

    uint64_t imm = 0;

    TCGv_i64 tcg_rd, tcg_imm;

    int i;

    if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {

        unallocated_encoding(s);

        return;

    }

    if (!fp_access_check(s)) {

        return;

    }

    /* See AdvSIMDExpandImm() in ARM ARM */

    switch (cmode_3_1) {

    case 0: /* Replicate(Zeros(24):imm8, 2) */

    case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */

    case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */

    case 3: /* Replicate(imm8:Zeros(24), 2) */

    {

        int shift = cmode_3_1 * 8;

        imm = bitfield_replicate(abcdefgh << shift, 32);

        break;

    }

    case 4: /* Replicate(Zeros(8):imm8, 4) */

    case 5: /* Replicate(imm8:Zeros(8), 4) */

    {

        int shift = (cmode_3_1 & 0x1) * 8;

        imm = bitfield_replicate(abcdefgh << shift, 16);

        break;

    }

    case 6:

        if (cmode_0) {

            /* Replicate(Zeros(8):imm8:Ones(16), 2) */

            imm = (abcdefgh << 16) | 0xffff;

        } else {

            /* Replicate(Zeros(16):imm8:Ones(8), 2) */

            imm = (abcdefgh << 8) | 0xff;

        }

        imm = bitfield_replicate(imm, 32);

        break;

    case 7:

        if (!cmode_0 && !is_neg) {

            imm = bitfield_replicate(abcdefgh, 8);

        } else if (!cmode_0 && is_neg) {

            int i;

            imm = 0;

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

                if ((abcdefgh) & (1 << i)) {

                    imm |= 0xffULL << (i * 8);

                }

            }

        } else if (cmode_0) {

            if (is_neg) {

                imm = (abcdefgh & 0x3f) << 48;

                if (abcdefgh & 0x80) {

                    imm |= 0x8000000000000000ULL;

                }

                if (abcdefgh & 0x40) {

                    imm |= 0x3fc0000000000000ULL;

                } else {

                    imm |= 0x4000000000000000ULL;

                }

            } else {

                imm = (abcdefgh & 0x3f) << 19;

                if (abcdefgh & 0x80) {

                    imm |= 0x80000000;

                }

                if (abcdefgh & 0x40) {

                    imm |= 0x3e000000;

                } else {

                    imm |= 0x40000000;

                }

                imm |= (imm << 32);

            }

        }

        break;

    }

    if (cmode_3_1 != 7 && is_neg) {

        imm = ~imm;

    }

    tcg_imm = tcg_const_i64(imm);

    tcg_rd = new_tmp_a64(s);

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

        int foffs = i ? fp_reg_hi_offset(rd) : fp_reg_offset(rd, MO_64);

        if (i == 1 && !is_q) {

            /* non-quad ops clear high half of vector */

            tcg_gen_movi_i64(tcg_rd, 0);

        } else if ((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9) {

            tcg_gen_ld_i64(tcg_rd, cpu_env, foffs);

            if (is_neg) {

                /* AND (BIC) */

                tcg_gen_and_i64(tcg_rd, tcg_rd, tcg_imm);

            } else {

                /* ORR */

                tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_imm);

            }

        } else {

            /* MOVI */

            tcg_gen_mov_i64(tcg_rd, tcg_imm);

        }

        tcg_gen_st_i64(tcg_rd, cpu_env, foffs);

    }

    tcg_temp_free_i64(tcg_imm);

}


int tcp_ctl(struct socket *so)

{

    Slirp *slirp = so->slirp;

    struct sbuf *sb = &so->so_snd;

    struct ex_list *ex_ptr;

    int do_pty;

    DEBUG_CALL("tcp_ctl");

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

    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {

        /* Check if it's pty_exec */

        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {

            if (ex_ptr->ex_fport == so->so_fport &&

                so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {

                if (ex_ptr->ex_pty == 3) {

                    so->s = -1;

                    so->extra = (void *)ex_ptr->ex_exec;

                    return 1;

                }

                do_pty = ex_ptr->ex_pty;

                DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));

                return fork_exec(so, ex_ptr->ex_exec, do_pty);

            }

        }

    }

    sb->sb_cc =

        snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),

                 "Error: No application configured.\r\n");

    sb->sb_wptr += sb->sb_cc;

    return 0;

}


void cpu_outl(CPUState *env, pio_addr_t addr, uint32_t val)

{

    LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);

    ioport_write(2, addr, val);

#ifdef CONFIG_KQEMU

    if (env)

        env->last_io_time = cpu_get_time_fast();

#endif

}


static int v9fs_synth_lsetxattr(FsContext *ctx, V9fsPath *path,

                                const char *name, void *value,

                                size_t size, int flags)

{

    errno = ENOTSUP;

    return -1;

}


static void register_types(void)

{

    register_char_driver_qapi("null", CHARDEV_BACKEND_KIND_NULL, NULL);

    register_char_driver("socket", qemu_chr_open_socket);

    register_char_driver("udp", qemu_chr_open_udp);

    register_char_driver("memory", qemu_chr_open_ringbuf);

    register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE,

                              qemu_chr_parse_file_out);

    register_char_driver_qapi("stdio", CHARDEV_BACKEND_KIND_STDIO,

                              qemu_chr_parse_stdio);

    register_char_driver_qapi("serial", CHARDEV_BACKEND_KIND_SERIAL,

                              qemu_chr_parse_serial);

    register_char_driver_qapi("tty", CHARDEV_BACKEND_KIND_SERIAL,

                              qemu_chr_parse_serial);

    register_char_driver_qapi("parallel", CHARDEV_BACKEND_KIND_PARALLEL,

                              qemu_chr_parse_parallel);

    register_char_driver_qapi("parport", CHARDEV_BACKEND_KIND_PARALLEL,

                              qemu_chr_parse_parallel);

#ifdef _WIN32

    register_char_driver("pipe", qemu_chr_open_win_pipe);

    register_char_driver("console", qemu_chr_open_win_con);

#else

    register_char_driver("pipe", qemu_chr_open_pipe);

#endif

#ifdef HAVE_CHARDEV_TTY

    register_char_driver("pty", qemu_chr_open_pty);

#endif

}


static void FUNCC(pred8x8_vertical_add)(uint8_t *pix, const int *block_offset,

                                        const int16_t *block, ptrdiff_t stride)

{

    int i;

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

        FUNCC(pred4x4_vertical_add)(pix + block_offset[i], block + i*16*sizeof(pixel), stride);

}


static inline void dv_decode_video_segment(DVVideoDecodeContext *s,

                                           UINT8 *buf_ptr1,

                                           const UINT16 *mb_pos_ptr)

{

    int quant, dc, dct_mode, class1, j;

    int mb_index, mb_x, mb_y, v, last_index;

    DCTELEM *block, *block1;

    int c_offset, bits_left;

    UINT8 *y_ptr;

    BlockInfo mb_data[5 * 6], *mb, *mb1;

    void (*idct_put)(UINT8 *dest, int line_size, DCTELEM *block);

    UINT8 *buf_ptr;

    PutBitContext pb, vs_pb;

    UINT8 mb_bit_buffer[80 + 4]; /* allow some slack */

    int mb_bit_count;

    UINT8 vs_bit_buffer[5 * 80 + 4]; /* allow some slack */

    int vs_bit_count;

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

    /* pass 1 : read DC and AC coefficients in blocks */

    buf_ptr = buf_ptr1;

    block1 = &s->block[0][0];

    mb1 = mb_data;

    init_put_bits(&vs_pb, vs_bit_buffer, 5 * 80, NULL, NULL);

    vs_bit_count = 0;

    for(mb_index = 0; mb_index < 5; mb_index++) {

        /* skip header */

        quant = buf_ptr[3] & 0x0f;

        buf_ptr += 4;

        init_put_bits(&pb, mb_bit_buffer, 80, NULL, NULL);

        mb_bit_count = 0;

        mb = mb1;

        block = block1;

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

            /* NOTE: size is not important here */

            init_get_bits(&s->gb, buf_ptr, 14);

            /* get the dc */

            dc = get_bits(&s->gb, 9);

            dc = (dc << (32 - 9)) >> (32 - 9);

            dct_mode = get_bits1(&s->gb);

            mb->dct_mode = dct_mode;

            mb->scan_table = s->dv_zigzag[dct_mode];

            class1 = get_bits(&s->gb, 2);

            mb->shift_offset = (class1 == 3);

            mb->shift_table = s->dv_shift[dct_mode]

                [quant + dv_quant_offset[class1]];

            dc = dc << 2;

            /* convert to unsigned because 128 is not added in the

               standard IDCT */

            dc += 1024;

            block[0] = dc;

            last_index = block_sizes[j];

            buf_ptr += last_index >> 3;

            mb->pos = 0;

            mb->partial_bit_count = 0;

            dv_decode_ac(s, mb, block, last_index);

            /* write the remaining bits  in a new buffer only if the

               block is finished */

            bits_left = last_index - s->gb.index;

            if (mb->eob_reached) {

                mb->partial_bit_count = 0;

                mb_bit_count += bits_left;

                bit_copy(&pb, &s->gb, bits_left);

            } else {

                /* should be < 16 bits otherwise a codeword could have

                   been parsed */

                mb->partial_bit_count = bits_left;

                mb->partial_bit_buffer = get_bits(&s->gb, bits_left);

            }

            block += 64;

            mb++;

        }

        flush_put_bits(&pb);

        /* pass 2 : we can do it just after */

#ifdef VLC_DEBUG

        printf("***pass 2 size=%d\n", mb_bit_count);

#endif

        block = block1;

        mb = mb1;

        init_get_bits(&s->gb, mb_bit_buffer, 80);

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

            if (!mb->eob_reached && s->gb.index < mb_bit_count) {

                dv_decode_ac(s, mb, block, mb_bit_count);

                /* if still not finished, no need to parse other blocks */

                if (!mb->eob_reached) {

                    /* we could not parse the current AC coefficient,

                       so we add the remaining bytes */

                    bits_left = mb_bit_count - s->gb.index;

                    if (bits_left > 0) {

                        mb->partial_bit_count += bits_left;

                        mb->partial_bit_buffer =

                            (mb->partial_bit_buffer << bits_left) |

                            get_bits(&s->gb, bits_left);

                    }

                    goto next_mb;

                }

            }

            block += 64;

            mb++;

        }

        /* all blocks are finished, so the extra bytes can be used at

           the video segment level */

        bits_left = mb_bit_count - s->gb.index;

        vs_bit_count += bits_left;

        bit_copy(&vs_pb, &s->gb, bits_left);

    next_mb:

        mb1 += 6;

        block1 += 6 * 64;

    }

    /* we need a pass other the whole video segment */

    flush_put_bits(&vs_pb);

#ifdef VLC_DEBUG

    printf("***pass 3 size=%d\n", vs_bit_count);

#endif

    block = &s->block[0][0];

    mb = mb_data;

    init_get_bits(&s->gb, vs_bit_buffer, 5 * 80);

    for(mb_index = 0; mb_index < 5; mb_index++) {

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

            if (!mb->eob_reached) {

#ifdef VLC_DEBUG

                printf("start %d:%d\n", mb_index, j);

#endif

                dv_decode_ac(s, mb, block, vs_bit_count);

            }

            block += 64;

            mb++;

        }

    }

    /* compute idct and place blocks */

    block = &s->block[0][0];

    mb = mb_data;

    for(mb_index = 0; mb_index < 5; mb_index++) {

        v = *mb_pos_ptr++;

        mb_x = v & 0xff;

        mb_y = v >> 8;

        y_ptr = s->current_picture[0] + (mb_y * s->linesize[0] * 8) + (mb_x * 8);

        if (s->sampling_411)

            c_offset = (mb_y * s->linesize[1] * 8) + ((mb_x >> 2) * 8);

        else

            c_offset = ((mb_y >> 1) * s->linesize[1] * 8) + ((mb_x >> 1) * 8);

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

            idct_put = s->idct_put[mb->dct_mode];

            if (j < 4) {

                if (s->sampling_411 && mb_x < (704 / 8)) {

                    /* NOTE: at end of line, the macroblock is handled as 420 */

                    idct_put(y_ptr + (j * 8), s->linesize[0], block);

                } else {

                    idct_put(y_ptr + ((j & 1) * 8) + ((j >> 1) * 8 * s->linesize[0]),

                             s->linesize[0], block);

                }

            } else {

                if (s->sampling_411 && mb_x >= (704 / 8)) {

                    uint8_t pixels[64], *c_ptr, *c_ptr1, *ptr;

                    int y, linesize;

                    /* NOTE: at end of line, the macroblock is handled as 420 */

                    idct_put(pixels, 8, block);

                    linesize = s->linesize[6 - j];

                    c_ptr = s->current_picture[6 - j] + c_offset;

                    ptr = pixels;

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

                        /* convert to 411P */

                        c_ptr1 = c_ptr + linesize;

                        c_ptr1[0] = c_ptr[0] = (ptr[0] + ptr[1]) >> 1;

                        c_ptr1[1] = c_ptr[1] = (ptr[2] + ptr[3]) >> 1;

                        c_ptr1[2] = c_ptr[2] = (ptr[4] + ptr[5]) >> 1;

                        c_ptr1[3] = c_ptr[3] = (ptr[6] + ptr[7]) >> 1;

                        c_ptr += linesize * 2;

                        ptr += 8;

                    }

                } else {

                    /* don't ask me why they inverted Cb and Cr ! */

                    idct_put(s->current_picture[6 - j] + c_offset,

                             s->linesize[6 - j], block);

                }

            }

            block += 64;

            mb++;

        }

    }

}


void helper_syscall(CPUX86State *env, int next_eip_addend)

{

    int selector;

    if (!(env->efer & MSR_EFER_SCE)) {

        raise_exception_err(env, EXCP06_ILLOP, 0);

    }

    selector = (env->star >> 32) & 0xffff;

    if (env->hflags & HF_LMA_MASK) {

        int code64;

        env->regs[R_ECX] = env->eip + next_eip_addend;

        env->regs[11] = cpu_compute_eflags(env);

        code64 = env->hflags & HF_CS64_MASK;

        env->eflags &= ~env->fmask;

        cpu_load_eflags(env, env->eflags, 0);

        cpu_x86_set_cpl(env, 0);

        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,

                           0, 0xffffffff,

                               DESC_G_MASK | DESC_P_MASK |

                               DESC_S_MASK |

                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |

                               DESC_L_MASK);

        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,

                               0, 0xffffffff,

                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                               DESC_S_MASK |

                               DESC_W_MASK | DESC_A_MASK);

        if (code64) {

            env->eip = env->lstar;

        } else {

            env->eip = env->cstar;

        }

    } else {

        env->regs[R_ECX] = (uint32_t)(env->eip + next_eip_addend);

        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);

        cpu_x86_set_cpl(env, 0);

        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,

                           0, 0xffffffff,

                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                               DESC_S_MASK |

                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);

        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,

                               0, 0xffffffff,

                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                               DESC_S_MASK |

                               DESC_W_MASK | DESC_A_MASK);

        env->eip = (uint32_t)env->star;

    }

}


static int net_socket_listen_init(NetClientState *peer,

                                  const char *model,

                                  const char *name,

                                  const char *host_str)

{

    NetClientState *nc;

    NetSocketState *s;

    struct sockaddr_in saddr;

    int fd, ret;

    Error *err = NULL;

    if (parse_host_port(&saddr, host_str, &err) < 0) {

        error_report_err(err);

        return -1;

    }

    fd = qemu_socket(PF_INET, SOCK_STREAM, 0);

    if (fd < 0) {

        perror("socket");

        return -1;

    }

    qemu_set_nonblock(fd);

    socket_set_fast_reuse(fd);

    ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));

    if (ret < 0) {

        perror("bind");

        closesocket(fd);

        return -1;

    }

    ret = listen(fd, 0);

    if (ret < 0) {

        perror("listen");

        closesocket(fd);

        return -1;

    }

    nc = qemu_new_net_client(&net_socket_info, peer, model, name);

    s = DO_UPCAST(NetSocketState, nc, nc);

    s->fd = -1;

    s->listen_fd = fd;

    s->nc.link_down = true;

    net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);

    qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);

    return 0;

}


static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,

                              BdrvCheckMode fix)

{

    BDRVQcowState *s = bs->opaque;

    uint64_t *l2_table = qemu_blockalign(bs, s->cluster_size);

    int ret;

    int refcount;

    int i, j;

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

        uint64_t l1_entry = s->l1_table[i];

        uint64_t l2_offset = l1_entry & L1E_OFFSET_MASK;

        bool l2_dirty = false;

        if (!l2_offset) {

            continue;

        }

        refcount = get_refcount(bs, l2_offset >> s->cluster_bits);

        if (refcount < 0) {

            /* don't print message nor increment check_errors */

            continue;

        }

        if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) {

            fprintf(stderr, "%s OFLAG_COPIED L2 cluster: l1_index=%d "

                    "l1_entry=%" PRIx64 " refcount=%d\n",

                    fix & BDRV_FIX_ERRORS ? "Repairing" :

                                            "ERROR",

                    i, l1_entry, refcount);

            if (fix & BDRV_FIX_ERRORS) {

                s->l1_table[i] = refcount == 1

                               ? l1_entry |  QCOW_OFLAG_COPIED

                               : l1_entry & ~QCOW_OFLAG_COPIED;

                ret = qcow2_write_l1_entry(bs, i);

                if (ret < 0) {

                    res->check_errors++;

                    goto fail;

                }

                res->corruptions_fixed++;

            } else {

                res->corruptions++;

            }

        }

        ret = bdrv_pread(bs->file, l2_offset, l2_table,

                         s->l2_size * sizeof(uint64_t));

        if (ret < 0) {

            fprintf(stderr, "ERROR: Could not read L2 table: %s\n",

                    strerror(-ret));

            res->check_errors++;

            goto fail;

        }

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

            uint64_t l2_entry = be64_to_cpu(l2_table[j]);

            uint64_t data_offset = l2_entry & L2E_OFFSET_MASK;

            int cluster_type = qcow2_get_cluster_type(l2_entry);

            if ((cluster_type == QCOW2_CLUSTER_NORMAL) ||

                ((cluster_type == QCOW2_CLUSTER_ZERO) && (data_offset != 0))) {

                refcount = get_refcount(bs, data_offset >> s->cluster_bits);

                if (refcount < 0) {

                    /* don't print message nor increment check_errors */

                    continue;

                }

                if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) {

                    fprintf(stderr, "%s OFLAG_COPIED data cluster: "

                            "l2_entry=%" PRIx64 " refcount=%d\n",

                            fix & BDRV_FIX_ERRORS ? "Repairing" :

                                                    "ERROR",

                            l2_entry, refcount);

                    if (fix & BDRV_FIX_ERRORS) {

                        l2_table[j] = cpu_to_be64(refcount == 1

                                    ? l2_entry |  QCOW_OFLAG_COPIED

                                    : l2_entry & ~QCOW_OFLAG_COPIED);

                        l2_dirty = true;

                        res->corruptions_fixed++;

                    } else {

                        res->corruptions++;

                    }

                }

            }

        }

        if (l2_dirty) {

            ret = qcow2_pre_write_overlap_check(bs,

                    QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2, l2_offset,

                    s->cluster_size);

            if (ret < 0) {

                fprintf(stderr, "ERROR: Could not write L2 table; metadata "

                        "overlap check failed: %s\n", strerror(-ret));

                res->check_errors++;

                goto fail;

            }

            ret = bdrv_pwrite(bs->file, l2_offset, l2_table, s->cluster_size);

            if (ret < 0) {

                fprintf(stderr, "ERROR: Could not write L2 table: %s\n",

                        strerror(-ret));

                res->check_errors++;

                goto fail;

            }

        }

    }

    ret = 0;

fail:

    qemu_vfree(l2_table);

    return ret;

}


static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,

                                         const char *name, int devfn,

                                         PCIConfigReadFunc *config_read,

                                         PCIConfigWriteFunc *config_write,

                                         uint8_t header_type)

{

    if (devfn < 0) {

        for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {

            if (!bus->devices[devfn])

                goto found;

        }

        return NULL;

    found: ;

    } else if (bus->devices[devfn]) {

        return NULL;

    }

    pci_dev->bus = bus;

    pci_dev->devfn = devfn;

    pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);

    memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));

    pci_config_alloc(pci_dev);

    header_type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;

    if (header_type == PCI_HEADER_TYPE_NORMAL) {

        pci_set_default_subsystem_id(pci_dev);

    }

    pci_init_cmask(pci_dev);

    pci_init_wmask(pci_dev);

    if (header_type == PCI_HEADER_TYPE_BRIDGE) {

        pci_init_wmask_bridge(pci_dev);

    }

    if (!config_read)

        config_read = pci_default_read_config;

    if (!config_write)

        config_write = pci_default_write_config;

    pci_dev->config_read = config_read;

    pci_dev->config_write = config_write;

    bus->devices[devfn] = pci_dev;

    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);

    pci_dev->version_id = 2; /* Current pci device vmstate version */

    return pci_dev;

}


static void put_int8(QEMUFile *f, void *pv, size_t size)

{

    int8_t *v = pv;

    qemu_put_s8s(f, v);

}


static void decode_q_branch(SnowContext *s, int level, int x, int y){

    const int w= s->b_width << s->block_max_depth;

    const int rem_depth= s->block_max_depth - level;

    const int index= (x + y*w) << rem_depth;

    int trx= (x+1)<<rem_depth;

    const BlockNode *left  = x ? &s->block[index-1] : &null_block;

    const BlockNode *top   = y ? &s->block[index-w] : &null_block;

    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;

    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt

    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;

    if(s->keyframe){

        set_blocks(s, level, x, y, null_block.color[0], null_block.color[1], null_block.color[2], null_block.mx, null_block.my, null_block.ref, BLOCK_INTRA);

        return;

    }

    if(level==s->block_max_depth || get_rac(&s->c, &s->block_state[4 + s_context])){

        int type, mx, my;

        int l = left->color[0];

        int cb= left->color[1];

        int cr= left->color[2];

        int ref = 0;

        int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);

        int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 0*av_log2(2*FFABS(tr->mx - top->mx));

        int my_context= av_log2(2*FFABS(left->my - top->my)) + 0*av_log2(2*FFABS(tr->my - top->my));

        type= get_rac(&s->c, &s->block_state[1 + left->type + top->type]) ? BLOCK_INTRA : 0;

        if(type){

            pred_mv(s, &mx, &my, 0, left, top, tr);

            l += get_symbol(&s->c, &s->block_state[32], 1);

            cb+= get_symbol(&s->c, &s->block_state[64], 1);

            cr+= get_symbol(&s->c, &s->block_state[96], 1);

        }else{

            if(s->ref_frames > 1)

                ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0);

            pred_mv(s, &mx, &my, ref, left, top, tr);

            mx+= get_symbol(&s->c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1);

            my+= get_symbol(&s->c, &s->block_state[128 + 32*(my_context + 16*!!ref)], 1);

        }

        set_blocks(s, level, x, y, l, cb, cr, mx, my, ref, type);

    }else{

        decode_q_branch(s, level+1, 2*x+0, 2*y+0);

        decode_q_branch(s, level+1, 2*x+1, 2*y+0);

        decode_q_branch(s, level+1, 2*x+0, 2*y+1);

        decode_q_branch(s, level+1, 2*x+1, 2*y+1);

    }

}


static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno)

{

    int compno, reslevelno, bandno, ret;

    Jpeg2000T1Context t1;

    Jpeg2000CodingStyle *codsty = &s->codsty;

    for (compno = 0; compno < s->ncomponents; compno++){

        Jpeg2000Component *comp = s->tile[tileno].comp + compno;

        av_log(s->avctx, AV_LOG_DEBUG,"dwt\n");

        if (ret = ff_dwt_encode(&comp->dwt, comp->i_data))

            return ret;

        av_log(s->avctx, AV_LOG_DEBUG,"after dwt -> tier1\n");

        for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){

            Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno;

            for (bandno = 0; bandno < reslevel->nbands ; bandno++){

                Jpeg2000Band *band = reslevel->band + bandno;

                Jpeg2000Prec *prec = band->prec; // we support only 1 precinct per band ATM in the encoder

                int cblkx, cblky, cblkno=0, xx0, x0, xx1, y0, yy0, yy1, bandpos;

                yy0 = bandno == 0 ? 0 : comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0];

                y0 = yy0;

                yy1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[1][0] + 1, band->log2_cblk_height) << band->log2_cblk_height,

                            band->coord[1][1]) - band->coord[1][0] + yy0;

                if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1])

                    continue;

                bandpos = bandno + (reslevelno > 0);

                for (cblky = 0; cblky < prec->nb_codeblocks_height; cblky++){

                    if (reslevelno == 0 || bandno == 1)

                        xx0 = 0;

                    else

                        xx0 = comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0];

                    x0 = xx0;

                    xx1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[0][0] + 1, band->log2_cblk_width) << band->log2_cblk_width,

                                band->coord[0][1]) - band->coord[0][0] + xx0;

                    for (cblkx = 0; cblkx < prec->nb_codeblocks_width; cblkx++, cblkno++){

                        int y, x;

                        if (codsty->transform == FF_DWT53){

                            for (y = yy0; y < yy1; y++){

                                int *ptr = t1.data[y-yy0];

                                for (x = xx0; x < xx1; x++){

                                    *ptr++ = comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] << NMSEDEC_FRACBITS;

                                }

                            }

                        } else{

                            for (y = yy0; y < yy1; y++){

                                int *ptr = t1.data[y-yy0];

                                for (x = xx0; x < xx1; x++){

                                    *ptr = (comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x]);

                                    *ptr = (int64_t)*ptr * (int64_t)(16384 * 65536 / band->i_stepsize) >> 14 - NMSEDEC_FRACBITS;

                                    ptr++;

                                }

                            }

                        }

                        encode_cblk(s, &t1, prec->cblk + cblkno, tile, xx1 - xx0, yy1 - yy0,

                                    bandpos, codsty->nreslevels - reslevelno - 1);

                        xx0 = xx1;

                        xx1 = FFMIN(xx1 + (1 << band->log2_cblk_width), band->coord[0][1] - band->coord[0][0] + x0);

                    }

                    yy0 = yy1;

                    yy1 = FFMIN(yy1 + (1 << band->log2_cblk_height), band->coord[1][1] - band->coord[1][0] + y0);

                }

            }

        }

        av_log(s->avctx, AV_LOG_DEBUG, "after tier1\n");

    }

    av_log(s->avctx, AV_LOG_DEBUG, "rate control\n");

    truncpasses(s, tile);

    if (ret = encode_packets(s, tile, tileno))

        return ret;

    av_log(s->avctx, AV_LOG_DEBUG, "after rate control\n");

    return 0;

}


static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,

                hwaddr base,

                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,

                omap_clk clk)

{

    struct omap_mpuio_s *s = (struct omap_mpuio_s *)

            g_malloc0(sizeof(struct omap_mpuio_s));

    s->irq = gpio_int;

    s->kbd_irq = kbd_int;

    s->wakeup = wakeup;

    s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);

    omap_mpuio_reset(s);

    memory_region_init_io(&s->iomem, NULL, &omap_mpuio_ops, s,

                          "omap-mpuio", 0x800);

    memory_region_add_subregion(memory, base, &s->iomem);

    omap_clk_adduser(clk, qemu_allocate_irq(omap_mpuio_onoff, s, 0));

    return s;

}


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

                        int dc_index, int ac_index, int16_t *quant_matrix)

{

    int code, i, j, level, val;

    /* DC coef */

    val = mjpeg_decode_dc(s, dc_index);

    if (val == 0xfffff) {

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

        return AVERROR_INVALIDDATA;

    }

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

    s->last_dc[component] = val;

    block[0] = val;

    /* AC coefs */

    i = 0;

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

    do {

        UPDATE_CACHE(re, &s->gb);

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

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

            code &= 0xf;

        if (code) {

            if (code > MIN_CACHE_BITS - 16)

                UPDATE_CACHE(re, &s->gb);

            {

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

                int sign  = (~cache) >> 31;

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

            }

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

            if (i > 63) {

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

                return AVERROR_INVALIDDATA;

            }

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

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

        }

    } while (i < 63);

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

    return 0;

}


static void iscsi_attach_aio_context(BlockDriverState *bs,

                                     AioContext *new_context)

{

    IscsiLun *iscsilun = bs->opaque;

    iscsilun->aio_context = new_context;

    iscsi_set_events(iscsilun);

#if defined(LIBISCSI_FEATURE_NOP_COUNTER)

    /* Set up a timer for sending out iSCSI NOPs */

    iscsilun->nop_timer = aio_timer_new(iscsilun->aio_context,

                                        QEMU_CLOCK_REALTIME, SCALE_MS,

                                        iscsi_nop_timed_event, iscsilun);

    timer_mod(iscsilun->nop_timer,

              qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);

#endif

}


static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)

{

    BDRVVPCState *s = bs->opaque;

    int64_t bat_offset;

    uint32_t index, bat_value;

    int ret;

    uint8_t bitmap[s->bitmap_size];

    // Check if sector_num is valid

    if ((sector_num < 0) || (sector_num > bs->total_sectors))

        return -1;

    // Write entry into in-memory BAT

    index = (sector_num * 512) / s->block_size;

    if (s->pagetable[index] != 0xFFFFFFFF)

        return -1;

    s->pagetable[index] = s->free_data_block_offset / 512;

    // Initialize the block's bitmap

    memset(bitmap, 0xff, s->bitmap_size);

    bdrv_pwrite(bs->file, s->free_data_block_offset, bitmap, s->bitmap_size);

    // Write new footer (the old one will be overwritten)

    s->free_data_block_offset += s->block_size + s->bitmap_size;

    ret = rewrite_footer(bs);

    if (ret < 0)

        goto fail;

    // Write BAT entry to disk

    bat_offset = s->bat_offset + (4 * index);

    bat_value = be32_to_cpu(s->pagetable[index]);

    ret = bdrv_pwrite(bs->file, bat_offset, &bat_value, 4);

    if (ret < 0)

        goto fail;

    return get_sector_offset(bs, sector_num, 0);

fail:

    s->free_data_block_offset -= (s->block_size + s->bitmap_size);

    return -1;

}


static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,

                       Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk,

                       int width, int height, int bandpos)

{

    int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y, clnpass_cnt = 0;

    int bpass_csty_symbol = JPEG2000_CBLK_BYPASS & codsty->cblk_style;

    int vert_causal_ctx_csty_symbol = JPEG2000_CBLK_VSC & codsty->cblk_style;

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

        memset(t1->data[y], 0, width * sizeof(**t1->data));

    /* If code-block contains no compressed data: nothing to do. */

    if (!cblk->length)

        return 0;

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

        memset(t1->flags[y], 0, (width + 2)*sizeof(**t1->flags));

    cblk->data[cblk->length] = 0xff;

    cblk->data[cblk->length+1] = 0xff;

    ff_mqc_initdec(&t1->mqc, cblk->data);

    while (passno--) {

        if (bpno < 0) {

            av_log(s->avctx, AV_LOG_ERROR, "bpno invalid\n");

            return AVERROR(EINVAL);

        }

        switch(pass_t) {

        case 0:

            decode_sigpass(t1, width, height, bpno + 1, bandpos,

                           bpass_csty_symbol && (clnpass_cnt >= 4), vert_causal_ctx_csty_symbol);

            break;

        case 1:

            decode_refpass(t1, width, height, bpno + 1);

            if (bpass_csty_symbol && clnpass_cnt >= 4)

                ff_mqc_initdec(&t1->mqc, cblk->data);

            break;

        case 2:

            decode_clnpass(s, t1, width, height, bpno + 1, bandpos,

                           codsty->cblk_style & JPEG2000_CBLK_SEGSYM, vert_causal_ctx_csty_symbol);

            clnpass_cnt = clnpass_cnt + 1;

            if (bpass_csty_symbol && clnpass_cnt >= 4)

                ff_mqc_initdec(&t1->mqc, cblk->data);

            break;

        }

        pass_t++;

        if (pass_t == 3) {

            bpno--;

            pass_t = 0;

        }

    }

    return 0;

}


static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)

{

    TCGv_i64 tmp;

    TCGv tmpl;

    TCGv tmph;

    /* Load 64-bit value rd:rn.  */

    tmpl = load_reg(s, rlow);

    tmph = load_reg(s, rhigh);

    tmp = tcg_temp_new_i64();

    tcg_gen_concat_i32_i64(tmp, tmpl, tmph);

    dead_tmp(tmpl);

    dead_tmp(tmph);

    tcg_gen_add_i64(val, val, tmp);

    tcg_temp_free_i64(tmp);

}


static int do_compress_ram_page(QEMUFile *f, RAMBlock *block,

                                ram_addr_t offset)

{

    RAMState *rs = &ram_state;

    int bytes_sent, blen;

    uint8_t *p = block->host + (offset & TARGET_PAGE_MASK);

    bytes_sent = save_page_header(rs, block, offset |

                                  RAM_SAVE_FLAG_COMPRESS_PAGE);

    blen = qemu_put_compression_data(f, p, TARGET_PAGE_SIZE,

                                     migrate_compress_level());

    if (blen < 0) {

        bytes_sent = 0;

        qemu_file_set_error(migrate_get_current()->to_dst_file, blen);

        error_report("compressed data failed!");

    } else {

        bytes_sent += blen;

        ram_release_pages(block->idstr, offset & TARGET_PAGE_MASK, 1);

    }

    return bytes_sent;

}


void ff_avg_h264_qpel4_mc11_msa(uint8_t *dst, const uint8_t *src,

                                ptrdiff_t stride)

{

    avc_luma_hv_qrt_and_aver_dst_4x4_msa(src - 2,

                                         src - (stride * 2),

                                         stride, dst, stride);

}


static int ra144_decode_frame(AVCodecContext * avctx,

            void *vdata, int *data_size,

            const uint8_t * buf, int buf_size)

{

    static const uint8_t sizes[10] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2};

    unsigned int a, b, c;

    int i;

    signed short *shptr;

    int16_t *data = vdata;

    unsigned int val;

    Real144_internal *glob = avctx->priv_data;

    GetBitContext gb;

    if(buf_size == 0)

        return 0;

    init_get_bits(&gb, buf, 20 * 8);

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

        // "<< 1"? Doesn't this make one value out of two of the table useless?

        glob->swapbuf1[i] = decodetable[i][get_bits(&gb, sizes[i]) << 1];

    do_voice(glob->swapbuf1, glob->swapbuf2);

    val = decodeval[get_bits(&gb, 5) << 1]; // Useless table entries?

    a = t_sqrt(val*glob->oldval) >> 12;

    for (c=0; c < NBLOCKS; c++) {

        if (c == (NBLOCKS - 1)) {

            dec1(glob, glob->swapbuf1, glob->swapbuf2, 3, val);

        } else {

            if (c * 2 == (NBLOCKS - 2)) {

                if (glob->oldval < val) {

                    dec2(glob, glob->swapbuf1, glob->swapbuf2, 3, a, glob->swapbuf2alt, c);

                } else {

                    dec2(glob, glob->swapbuf1alt, glob->swapbuf2alt, 3, a, glob->swapbuf2, c);

                }

            } else {

                if (c * 2 < (NBLOCKS - 2)) {

                    dec2(glob, glob->swapbuf1alt, glob->swapbuf2alt, 3, glob->oldval, glob->swapbuf2, c);

                } else {

                    dec2(glob, glob->swapbuf1, glob->swapbuf2, 3, val, glob->swapbuf2alt, c);

                }

            }

        }

    }

    /* do output */

    for (b=0, c=0; c<4; c++) {

        unsigned int gval = glob->gbuf1[c * 2];

        unsigned short *gsp = glob->gbuf2 + b;

        signed short output_buffer[40];

        do_output_subblock(glob, gsp, gval, output_buffer, &gb);

        shptr = output_buffer;

        while (shptr < output_buffer + BLOCKSIZE)

            *data++ = av_clip_int16(*(shptr++) << 2);

        b += 30;

    }

    glob->oldval = val;

    FFSWAP(unsigned int *, glob->swapbuf1alt, glob->swapbuf1);

    FFSWAP(unsigned int *, glob->swapbuf2alt, glob->swapbuf2);

    *data_size = 2*160;

    return 20;

}


static int h261_decode_picture_header(H261Context *h)

{

    MpegEncContext *const s = &h->s;

    int format, i;

    uint32_t startcode = 0;

    for (i = get_bits_left(&s->gb); i > 24; i -= 1) {

        startcode = ((startcode << 1) | get_bits(&s->gb, 1)) & 0x000FFFFF;

        if (startcode == 0x10)

            break;

    }

    if (startcode != 0x10) {

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

        return -1;

    }

    /* temporal reference */

    i = get_bits(&s->gb, 5); /* picture timestamp */

    if (i < (s->picture_number & 31))

        i += 32;

    s->picture_number = (s->picture_number & ~31) + i;

    s->avctx->time_base      = (AVRational) { 1001, 30000 };

    /* PTYPE starts here */

    skip_bits1(&s->gb); /* split screen off */

    skip_bits1(&s->gb); /* camera  off */

    skip_bits1(&s->gb); /* freeze picture release off */

    format = get_bits1(&s->gb);

    // only 2 formats possible

    if (format == 0) { // QCIF

        s->width     = 176;

        s->height    = 144;

        s->mb_width  = 11;

        s->mb_height = 9;

    } else { // CIF

        s->width     = 352;

        s->height    = 288;

        s->mb_width  = 22;

        s->mb_height = 18;

    }

    s->mb_num = s->mb_width * s->mb_height;

    skip_bits1(&s->gb); /* still image mode off */

    skip_bits1(&s->gb); /* Reserved */

    /* PEI */

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

        skip_bits(&s->gb, 8);

    /* H.261 has no I-frames, but if we pass AV_PICTURE_TYPE_I for the first

     * frame, the codec crashes if it does not contain all I-blocks

     * (e.g. when a packet is lost). */

    s->pict_type = AV_PICTURE_TYPE_P;

    h->gob_number = 0;

    return 0;

}


static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp)

{

    PowerPCCPU *cpu = POWERPC_CPU(dev);

    CPUPPCState *env = &cpu->env;

    opc_handler_t **table;

    int i, j;

    cpu_exec_exit(CPU(dev));

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

        if (env->opcodes[i] == &invalid_handler) {

            continue;

        }

        if (is_indirect_opcode(env->opcodes[i])) {

            table = ind_table(env->opcodes[i]);

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

                if (table[j] != &invalid_handler &&

                        is_indirect_opcode(table[j])) {

                    g_free((opc_handler_t *)((uintptr_t)table[j] &

                        ~PPC_INDIRECT));

                }

            }

            g_free((opc_handler_t *)((uintptr_t)env->opcodes[i] &

                ~PPC_INDIRECT));

        }

    }

}


static void h261_decode_init_vlc(H261Context *h){

    static int done = 0;

    if(!done){

        done = 1;

        init_vlc(&h261_mba_vlc, H261_MBA_VLC_BITS, 35,

                 h261_mba_bits, 1, 1,

                 h261_mba_code, 1, 1);

        init_vlc(&h261_mtype_vlc, H261_MTYPE_VLC_BITS, 10,

                 h261_mtype_bits, 1, 1,

                 h261_mtype_code, 1, 1);

        init_vlc(&h261_mv_vlc, H261_MV_VLC_BITS, 17,

                 &h261_mv_tab[0][1], 2, 1,

                 &h261_mv_tab[0][0], 2, 1);

        init_vlc(&h261_cbp_vlc, H261_CBP_VLC_BITS, 63,

                 &h261_cbp_tab[0][1], 2, 1,

                 &h261_cbp_tab[0][0], 2, 1);

        init_rl(&h261_rl_tcoeff);

        init_vlc_rl(&h261_rl_tcoeff);

    }

}


static void init_proc_750cl (CPUPPCState *env)

{

    gen_spr_ne_601(env);

    gen_spr_7xx(env);

    /* XXX : not implemented */

    spr_register(env, SPR_L2CR, "L2CR",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, NULL,

                 0x00000000);

    /* Time base */

    gen_tbl(env);

    /* Thermal management */

    /* Those registers are fake on 750CL */

    spr_register(env, SPR_THRM1, "THRM1",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    spr_register(env, SPR_THRM2, "THRM2",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    spr_register(env, SPR_THRM3, "THRM3",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX: not implemented */

    spr_register(env, SPR_750_TDCL, "TDCL",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    spr_register(env, SPR_750_TDCH, "TDCH",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* DMA */

    /* XXX : not implemented */

    spr_register(env, SPR_750_WPAR, "WPAR",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    spr_register(env, SPR_750_DMAL, "DMAL",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    spr_register(env, SPR_750_DMAU, "DMAU",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* Hardware implementation registers */

    /* XXX : not implemented */

    spr_register(env, SPR_HID0, "HID0",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_HID1, "HID1",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750CL_HID2, "HID2",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750CL_HID4, "HID4",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* Quantization registers */

    /* XXX : not implemented */

    spr_register(env, SPR_750_GQR0, "GQR0",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750_GQR1, "GQR1",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750_GQR2, "GQR2",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750_GQR3, "GQR3",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750_GQR4, "GQR4",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750_GQR5, "GQR5",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750_GQR6, "GQR6",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* XXX : not implemented */

    spr_register(env, SPR_750_GQR7, "GQR7",

                 SPR_NOACCESS, SPR_NOACCESS,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

    /* Memory management */

    gen_low_BATs(env);

    /* PowerPC 750cl has 8 DBATs and 8 IBATs */

    gen_high_BATs(env);

    init_excp_750cl(env);

    env->dcache_line_size = 32;

    env->icache_line_size = 32;

    /* Allocate hardware IRQ controller */

    ppc6xx_irq_init(env);

}


static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr,

                               target_ulong opcode, target_ulong *args)

{

    CPUState *cs;

    target_ulong mflags = args[0];

    target_ulong resource = args[1];

    target_ulong value1 = args[2];

    target_ulong value2 = args[3];

    target_ulong ret = H_P2;

    if (resource == H_SET_MODE_ENDIAN) {

        if (value1) {

            ret = H_P3;

            goto out;

        }

        if (value2) {

            ret = H_P4;

            goto out;

        }

        switch (mflags) {

        case H_SET_MODE_ENDIAN_BIG:

            CPU_FOREACH(cs) {

                PowerPCCPU *cp = POWERPC_CPU(cs);

                CPUPPCState *env = &cp->env;

                env->spr[SPR_LPCR] &= ~LPCR_ILE;

            }

            ret = H_SUCCESS;

            break;

        case H_SET_MODE_ENDIAN_LITTLE:

            CPU_FOREACH(cs) {

                PowerPCCPU *cp = POWERPC_CPU(cs);

                CPUPPCState *env = &cp->env;

                env->spr[SPR_LPCR] |= LPCR_ILE;

            }

            ret = H_SUCCESS;

            break;

        default:

            ret = H_UNSUPPORTED_FLAG;

        }

    }

out:

    return ret;

}


static int xan_wc3_decode_frame(XanContext *s) {

    int width = s->avctx->width;

    int height = s->avctx->height;

    int total_pixels = width * height;

    unsigned char opcode;

    unsigned char flag = 0;

    int size = 0;

    int motion_x, motion_y;

    int x, y;

    unsigned char *opcode_buffer = s->buffer1;

    unsigned char *opcode_buffer_end = s->buffer1 + s->buffer1_size;

    int opcode_buffer_size = s->buffer1_size;

    const unsigned char *imagedata_buffer = s->buffer2;

    /* pointers to segments inside the compressed chunk */

    const unsigned char *huffman_segment;

    const unsigned char *size_segment;

    const unsigned char *vector_segment;

    const unsigned char *imagedata_segment;

    int huffman_offset, size_offset, vector_offset, imagedata_offset, imagedata_size;

    if (s->size < 8)

        return AVERROR_INVALIDDATA;

    huffman_offset    = AV_RL16(&s->buf[0]);

    size_offset       = AV_RL16(&s->buf[2]);

    vector_offset     = AV_RL16(&s->buf[4]);

    imagedata_offset  = AV_RL16(&s->buf[6]);

    if (huffman_offset   >= s->size ||

        size_offset      >= s->size ||

        vector_offset    >= s->size ||

        imagedata_offset >= s->size)

        return AVERROR_INVALIDDATA;

    huffman_segment   = s->buf + huffman_offset;

    size_segment      = s->buf + size_offset;

    vector_segment    = s->buf + vector_offset;

    imagedata_segment = s->buf + imagedata_offset;

    if (xan_huffman_decode(opcode_buffer, opcode_buffer_size,

                           huffman_segment, s->size - huffman_offset) < 0)

        return AVERROR_INVALIDDATA;

    if (imagedata_segment[0] == 2) {

        xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size);

        imagedata_size = s->buffer2_size;

    } else {

        imagedata_size = s->size - imagedata_offset - 1;

        imagedata_buffer = &imagedata_segment[1];

    }

    /* use the decoded data segments to build the frame */

    x = y = 0;

    while (total_pixels && opcode_buffer < opcode_buffer_end) {

        opcode = *opcode_buffer++;

        size = 0;

        switch (opcode) {

        case 0:

            flag ^= 1;

            continue;

        case 1:

        case 2:

        case 3:

        case 4:

        case 5:

        case 6:

        case 7:

        case 8:

            size = opcode;

            break;

        case 12:

        case 13:

        case 14:

        case 15:

        case 16:

        case 17:

        case 18:

            size += (opcode - 10);

            break;

        case 9:

        case 19:

            size = *size_segment++;

            break;

        case 10:

        case 20:

            size = AV_RB16(&size_segment[0]);

            size_segment += 2;

            break;

        case 11:

        case 21:

            size = AV_RB24(size_segment);

            size_segment += 3;

            break;

        }

        if (size > total_pixels)

            break;

        if (opcode < 12) {

            flag ^= 1;

            if (flag) {

                /* run of (size) pixels is unchanged from last frame */

                xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);

            } else {

                /* output a run of pixels from imagedata_buffer */

                if (imagedata_size < size)

                    break;

                xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);

                imagedata_buffer += size;

                imagedata_size -= size;

            }

        } else {

            /* run-based motion compensation from last frame */

            motion_x = sign_extend(*vector_segment >> 4,  4);

            motion_y = sign_extend(*vector_segment & 0xF, 4);

            vector_segment++;

            /* copy a run of pixels from the previous frame */

            xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);

            flag = 0;

        }

        /* coordinate accounting */

        total_pixels -= size;

        y += (x + size) / width;

        x  = (x + size) % width;

    }

    return 0;

}