Skip to content
Snippets Groups Projects
utils.c 59.7 KiB
Newer Older
  • Learn to ignore specific revisions
  •     if (flags & SWS_FAST_BILINEAR) {
    
                c->lumXInc += 20;
                c->chrXInc += 20;
    
            // we don't use the x86 asm scaler if MMX is available
    
                c->lumXInc = ((int64_t)(srcW       - 2) << 16) / (dstW       - 2) - 20;
                c->chrXInc = ((int64_t)(c->chrSrcW - 2) << 16) / (c->chrDstW - 2) - 20;
    
            }
        }
    
        /* precalculate horizontal scaler filter coefficients */
        {
    
    #if HAVE_MMXEXT_INLINE
    
    // 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);
    
                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)
    
                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_MMXEXT_INLINE */
    
                const int filterAlign =
                    (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 4 :
    
                    (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
    
                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, 1) < 0)
    
                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, 1) < 0)
    
                    goto fail;
            }
        } // initialize horizontal stuff
    
        /* precalculate vertical scaler filter coefficients */
        {
    
            const int filterAlign =
                (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 2 :
    
                (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
    
            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) < 0)
    
            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) < 0)
    
            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++)
    
            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      = (int64_t)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 * 3 * sizeof(int16_t *), fail);
        FF_ALLOC_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
        FF_ALLOC_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
    
        if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))
    
            FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
        /* Note we need at least one pixel more at the end because of the MMX code
         * (just in case someone wants to 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 + 16, fail);
            c->lumPixBuf[i] = c->lumPixBuf[i + c->vLumBufSize];
    
        // 64 / (c->dstBpc & ~7) is the same as 16 / sizeof(scaling_intermediate)
    
        c->uv_off_px   = dst_stride_px + 64 / (c->dstBpc & ~7);
    
        c->uv_off_byte = dst_stride + 16;
    
        for (i = 0; i < c->vChrBufSize; i++) {
            FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i + c->vChrBufSize],
                             dst_stride * 2 + 32, fail);
            c->chrUPixBuf[i] = c->chrUPixBuf[i + c->vChrBufSize];
            c->chrVPixBuf[i] = c->chrVPixBuf[i + c->vChrBufSize]
                             = c->chrUPixBuf[i] + (dst_stride >> 1) + 8;
    
        }
        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 + 16, 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);
    
        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 == AV_PIX_FMT_BGR555   || dstFormat == AV_PIX_FMT_BGR565   ||
                   dstFormat == AV_PIX_FMT_RGB444BE || dstFormat == AV_PIX_FMT_RGB444LE ||
                   dstFormat == AV_PIX_FMT_BGR444BE || dstFormat == AV_PIX_FMT_BGR444LE ?
    
                                                                 "dithered " : "",
    
                av_log(c, AV_LOG_INFO, "using MMX2\n");
    
            else if (INLINE_AMD3DNOW(cpu_flags))
    
                av_log(c, AV_LOG_INFO, "using 3DNOW\n");
    
                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");
    
    
            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);
    
    fail: // FIXME replace things by appropriate error codes
    
    SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
                               int dstW, int dstH, enum AVPixelFormat dstFormat,
    
                               int flags, SwsFilter *srcFilter,
                               SwsFilter *dstFilter, const double *param)
    
        if (!(c = sws_alloc_context()))
    
        c->flags     = flags;
        c->srcW      = srcW;
        c->srcH      = srcH;
        c->dstW      = dstW;
        c->dstH      = dstH;
        c->srcRange  = handle_jpeg(&srcFormat);
        c->dstRange  = handle_jpeg(&dstFormat);
        c->srcFormat = srcFormat;
        c->dstFormat = dstFormat;
    
    
        if (param) {
            c->param[0] = param[0];
            c->param[1] = param[1];
        }
    
        sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange,
                                 ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
                                 c->dstRange, 0, 1 << 16, 1 << 16);
    
        if (sws_init_context(c, srcFilter, dstFilter) < 0) {
    
    
    SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
                                    float lumaSharpen, float chromaSharpen,
                                    float chromaHShift, float chromaVShift,
                                    int verbose)
    {
    
        SwsFilter *filter = av_malloc(sizeof(SwsFilter));
    
        if (lumaGBlur != 0.0) {
            filter->lumH = sws_getGaussianVec(lumaGBlur, 3.0);
            filter->lumV = sws_getGaussianVec(lumaGBlur, 3.0);
    
            filter->lumH = sws_getIdentityVec();
            filter->lumV = sws_getIdentityVec();
    
        if (chromaGBlur != 0.0) {
            filter->chrH = sws_getGaussianVec(chromaGBlur, 3.0);
            filter->chrV = sws_getGaussianVec(chromaGBlur, 3.0);
    
            filter->chrH = sws_getIdentityVec();
            filter->chrV = sws_getIdentityVec();
    
        if (chromaSharpen != 0.0) {
            SwsVector *id = sws_getIdentityVec();
    
            sws_scaleVec(filter->chrH, -chromaSharpen);
            sws_scaleVec(filter->chrV, -chromaSharpen);
            sws_addVec(filter->chrH, id);
            sws_addVec(filter->chrV, id);
            sws_freeVec(id);
        }
    
    
        if (lumaSharpen != 0.0) {
            SwsVector *id = sws_getIdentityVec();
    
            sws_scaleVec(filter->lumH, -lumaSharpen);
            sws_scaleVec(filter->lumV, -lumaSharpen);
            sws_addVec(filter->lumH, id);
            sws_addVec(filter->lumV, id);
            sws_freeVec(id);
        }
    
        if (chromaHShift != 0.0)
    
            sws_shiftVec(filter->chrH, (int)(chromaHShift + 0.5));
    
            sws_shiftVec(filter->chrV, (int)(chromaVShift + 0.5));
    
    
        sws_normalizeVec(filter->chrH, 1.0);
        sws_normalizeVec(filter->chrV, 1.0);
        sws_normalizeVec(filter->lumH, 1.0);
        sws_normalizeVec(filter->lumV, 1.0);
    
    
        if (verbose)
            sws_printVec2(filter->chrH, NULL, AV_LOG_DEBUG);
        if (verbose)
            sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG);
    
    
        return filter;
    }
    
    SwsVector *sws_allocVec(int length)
    {
        SwsVector *vec = av_malloc(sizeof(SwsVector));
        if (!vec)
            return NULL;
        vec->length = length;
        vec->coeff  = av_malloc(sizeof(double) * length);
        if (!vec->coeff)
            av_freep(&vec);
        return vec;
    }
    
    SwsVector *sws_getGaussianVec(double variance, double quality)
    {
    
        const int length = (int)(variance * quality + 0.5) | 1;
    
        double middle  = (length - 1) * 0.5;
        SwsVector *vec = sws_allocVec(length);
    
        for (i = 0; i < length; i++) {
            double dist = i - middle;
            vec->coeff[i] = exp(-dist * dist / (2 * variance * variance)) /
                            sqrt(2 * variance * M_PI);
    
        }
    
        sws_normalizeVec(vec, 1.0);
    
        return vec;
    }
    
    SwsVector *sws_getConstVec(double c, int length)
    {
        int i;
    
        SwsVector *vec = sws_allocVec(length);
    
        for (i = 0; i < length; i++)
            vec->coeff[i] = c;
    
    
        return vec;
    }
    
    SwsVector *sws_getIdentityVec(void)
    {
        return sws_getConstVec(1.0, 1);
    }
    
    
    static double sws_dcVec(SwsVector *a)
    
        for (i = 0; i < a->length; i++)
            sum += a->coeff[i];
    
    
        return sum;
    }
    
    void sws_scaleVec(SwsVector *a, double scalar)
    {
        int i;
    
    
        for (i = 0; i < a->length; i++)
            a->coeff[i] *= scalar;
    
    }
    
    void sws_normalizeVec(SwsVector *a, double height)
    {
    
        sws_scaleVec(a, height / sws_dcVec(a));
    
    }
    
    static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b)
    {
    
        int length = a->length + b->length - 1;
    
        SwsVector *vec = sws_getConstVec(0.0, length);
    
        for (i = 0; i < a->length; i++) {
            for (j = 0; j < b->length; j++) {
                vec->coeff[i + j] += a->coeff[i] * b->coeff[j];
    
            }
        }
    
        return vec;
    }
    
    static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b)
    {
    
        int length = FFMAX(a->length, b->length);
    
        SwsVector *vec = sws_getConstVec(0.0, length);
    
        for (i = 0; i < a->length; i++)
            vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
        for (i = 0; i < b->length; i++)
            vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] += b->coeff[i];
    
    
        return vec;
    }
    
    static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b)
    {
    
        int length = FFMAX(a->length, b->length);
    
        SwsVector *vec = sws_getConstVec(0.0, length);
    
        for (i = 0; i < a->length; i++)
            vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
        for (i = 0; i < b->length; i++)
            vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] -= b->coeff[i];
    
    
        return vec;
    }
    
    /* shift left / or right if "shift" is negative */
    static SwsVector *sws_getShiftedVec(SwsVector *a, int shift)
    {
    
        int length = a->length + FFABS(shift) * 2;
    
        SwsVector *vec = sws_getConstVec(0.0, length);
    
        for (i = 0; i < a->length; i++) {
            vec->coeff[i + (length    - 1) / 2 -
                           (a->length - 1) / 2 - shift] = a->coeff[i];
    
        SwsVector *shifted = sws_getShiftedVec(a, shift);
    
        a->coeff  = shifted->coeff;
        a->length = shifted->length;
    
        av_free(shifted);
    }
    
    void sws_addVec(SwsVector *a, SwsVector *b)
    {
    
        SwsVector *sum = sws_sumVec(a, b);
    
        a->coeff  = sum->coeff;
        a->length = sum->length;
    
        av_free(sum);
    }
    
    void sws_subVec(SwsVector *a, SwsVector *b)
    {
    
        SwsVector *diff = sws_diffVec(a, b);
    
        a->coeff  = diff->coeff;
        a->length = diff->length;
    
        av_free(diff);
    }
    
    void sws_convVec(SwsVector *a, SwsVector *b)
    {
    
        SwsVector *conv = sws_getConvVec(a, b);
    
        a->coeff  = conv->coeff;
        a->length = conv->length;
    
        av_free(conv);
    }
    
    SwsVector *sws_cloneVec(SwsVector *a)
    {
        int i;
    
        SwsVector *vec = sws_allocVec(a->length);
    
        for (i = 0; i < a->length; i++)
            vec->coeff[i] = a->coeff[i];
    
    
        return vec;
    }
    
    void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level)
    {
        int i;
    
        double max = 0;
        double min = 0;
    
        for (i = 0; i < a->length; i++)
            if (a->coeff[i] > max)
                max = a->coeff[i];
    
        for (i = 0; i < a->length; i++)
            if (a->coeff[i] < min)
                min = a->coeff[i];
    
        range = max - min;
    
        for (i = 0; i < a->length; i++) {
            int x = (int)((a->coeff[i] - min) * 60.0 / range + 0.5);
    
            av_log(log_ctx, log_level, "%1.3f ", a->coeff[i]);
    
            for (; x > 0; x--)
                av_log(log_ctx, log_level, " ");
    
            av_log(log_ctx, log_level, "|\n");
        }
    }
    
    void sws_freeVec(SwsVector *a)
    {
    
        av_free(a);
    }
    
    void sws_freeFilter(SwsFilter *filter)
    {
    
        if (!filter)
            return;
    
        if (filter->lumH)
            sws_freeVec(filter->lumH);
        if (filter->lumV)
            sws_freeVec(filter->lumV);
        if (filter->chrH)
            sws_freeVec(filter->chrH);
        if (filter->chrV)
            sws_freeVec(filter->chrV);
    
        av_free(filter);
    }
    
    void sws_freeContext(SwsContext *c)
    {
        int i;
    
            for (i = 0; i < c->vLumBufSize; i++)
    
                av_freep(&c->lumPixBuf[i]);
            av_freep(&c->lumPixBuf);
        }
    
    
            for (i = 0; i < c->vChrBufSize; i++)
    
                av_freep(&c->chrUPixBuf[i]);
            av_freep(&c->chrUPixBuf);
            av_freep(&c->chrVPixBuf);
    
        }
    
        if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
    
            for (i = 0; i < c->vLumBufSize; i++)
    
                av_freep(&c->alpPixBuf[i]);
            av_freep(&c->alpPixBuf);
        }
    
        av_freep(&c->vLumFilter);
        av_freep(&c->vChrFilter);
        av_freep(&c->hLumFilter);
        av_freep(&c->hChrFilter);
    
        av_freep(&c->vYCoeffsBank);
        av_freep(&c->vCCoeffsBank);
    #endif
    
        av_freep(&c->vLumFilterPos);
        av_freep(&c->vChrFilterPos);
        av_freep(&c->hLumFilterPos);
        av_freep(&c->hChrFilterPos);
    
    
    #if HAVE_MMX_INLINE
    
        if (c->lumMmx2FilterCode)
            munmap(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize);
        if (c->chrMmx2FilterCode)
            munmap(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize);
    
        if (c->lumMmx2FilterCode)
            VirtualFree(c->lumMmx2FilterCode, 0, MEM_RELEASE);
        if (c->chrMmx2FilterCode)
            VirtualFree(c->chrMmx2FilterCode, 0, MEM_RELEASE);
    
    #else
        av_free(c->lumMmx2FilterCode);
        av_free(c->chrMmx2FilterCode);
    #endif
    
        c->lumMmx2FilterCode = NULL;
        c->chrMmx2FilterCode = NULL;
    
    #endif /* HAVE_MMX_INLINE */
    
        av_free(c->formatConvBuffer);
    
    struct SwsContext *sws_getCachedContext(struct SwsContext *context, int srcW,
    
                                            int srcH, enum AVPixelFormat srcFormat,
    
                                            int dstW, int dstH,
    
                                            enum AVPixelFormat dstFormat, int flags,
    
                                            SwsFilter *srcFilter,
                                            SwsFilter *dstFilter,
                                            const double *param)
    
        static const double default_param[2] = { SWS_PARAM_DEFAULT,
                                                 SWS_PARAM_DEFAULT };
    
            (context->srcW      != srcW      ||
             context->srcH      != srcH      ||
             context->srcFormat != srcFormat ||
             context->dstW      != dstW      ||
             context->dstH      != dstH      ||
             context->dstFormat != dstFormat ||
             context->flags     != flags     ||
             context->param[0]  != param[0]  ||
    
             context->param[1]  != param[1])) {
            sws_freeContext(context);
            context = NULL;
        }
    
            if (!(context = sws_alloc_context()))
                return NULL;
            context->srcW      = srcW;
            context->srcH      = srcH;
    
            context->srcRange  = handle_jpeg(&srcFormat);
    
            context->srcFormat = srcFormat;
    
            context->dstW      = dstW;
            context->dstH      = dstH;
    
            context->dstRange  = handle_jpeg(&dstFormat);
    
            context->dstFormat = dstFormat;
            context->flags     = flags;
            context->param[0]  = param[0];
            context->param[1]  = param[1];
    
            sws_setColorspaceDetails(context, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
                                     context->srcRange,
                                     ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
                                     context->dstRange, 0, 1 << 16, 1 << 16);
    
            if (sws_init_context(context, srcFilter, dstFilter) < 0) {
                sws_freeContext(context);
                return NULL;
            }