Skip to content
Snippets Groups Projects
utils.c 76.5 KiB
Newer Older
  • Learn to ignore specific revisions
  •     c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
        c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
    
        if (!isYUV(c->dstFormat) && !isGray(c->dstFormat)) {
    
            ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness,
                                     contrast, saturation);
            // FIXME factorize
    
            if (ARCH_PPC)
                ff_yuv2rgb_init_tables_ppc(c, inv_table, brightness,
                                           contrast, saturation);
    
    
        fill_rgb2yuv_table(c, table, dstRange);
    
    
    int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
                                 int *srcRange, int **table, int *dstRange,
                                 int *brightness, int *contrast, int *saturation)
    
        *inv_table  = c->srcColorspaceTable;
        *table      = c->dstColorspaceTable;
        *srcRange   = c->srcRange;
        *dstRange   = c->dstRange;
        *brightness = c->brightness;
        *contrast   = c->contrast;
        *saturation = c->saturation;
    
    static int handle_jpeg(enum AVPixelFormat *format)
    
        case AV_PIX_FMT_YUVJ420P:
            *format = AV_PIX_FMT_YUV420P;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        case AV_PIX_FMT_YUVJ411P:
            *format = AV_PIX_FMT_YUV411P;
            return 1;
    
        case AV_PIX_FMT_YUVJ422P:
            *format = AV_PIX_FMT_YUV422P;
    
        case AV_PIX_FMT_YUVJ444P:
            *format = AV_PIX_FMT_YUV444P;
    
        case AV_PIX_FMT_YUVJ440P:
            *format = AV_PIX_FMT_YUV440P;
    
        case AV_PIX_FMT_GRAY16LE:
        case AV_PIX_FMT_GRAY16BE:
    
    static int handle_0alpha(enum AVPixelFormat *format)
    
        case AV_PIX_FMT_0BGR    : *format = AV_PIX_FMT_ABGR   ; return 1;
        case AV_PIX_FMT_BGR0    : *format = AV_PIX_FMT_BGRA   ; return 4;
        case AV_PIX_FMT_0RGB    : *format = AV_PIX_FMT_ARGB   ; return 1;
        case AV_PIX_FMT_RGB0    : *format = AV_PIX_FMT_RGBA   ; return 4;
    
    static int handle_xyz(enum AVPixelFormat *format)
    {
        switch (*format) {
        case AV_PIX_FMT_XYZ12BE : *format = AV_PIX_FMT_RGB48BE; return 1;
        case AV_PIX_FMT_XYZ12LE : *format = AV_PIX_FMT_RGB48LE; return 1;
        default:                                                return 0;
        }
    }
    
    
    static void handle_formats(SwsContext *c)
    {
    
        c->src0Alpha |= handle_0alpha(&c->srcFormat);
        c->dst0Alpha |= handle_0alpha(&c->dstFormat);
        c->srcXYZ    |= handle_xyz(&c->srcFormat);
        c->dstXYZ    |= handle_xyz(&c->dstFormat);
    
        if (c->srcXYZ || c->dstXYZ)
            fill_xyztables(c);
    
    SwsContext *sws_alloc_context(void)
    {
    
        SwsContext *c = av_mallocz(sizeof(SwsContext));
    
        if (c) {
            c->av_class = &sws_context_class;
            av_opt_set_defaults(c);
        }
    
    av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
                                 SwsFilter *dstFilter)
    
        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) + 66, 16);
    
        enum AVPixelFormat srcFormat = c->srcFormat;
        enum AVPixelFormat dstFormat = c->dstFormat;
    
        const AVPixFmtDescriptor *desc_src;
        const AVPixFmtDescriptor *desc_dst;
    
        cpu_flags = av_get_cpu_flags();
        flags     = c->flags;
    
    Ronald S. Bultje's avatar
    Ronald S. Bultje committed
        emms_c();
    
        if (!rgb15to16)
            sws_rgb2rgb_init();
    
        c->srcRange |= handle_jpeg(&c->srcFormat);
        c->dstRange |= handle_jpeg(&c->dstFormat);
    
    
        if(srcFormat!=c->srcFormat || dstFormat!=c->dstFormat)
            av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
    
    
        if (!c->contrast && !c->saturation && !c->dstFormatBpp)
            sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange,
                                     ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
                                     c->dstRange, 0, 1 << 16, 1 << 16);
    
    
        handle_formats(c);
        srcFormat = c->srcFormat;
        dstFormat = c->dstFormat;
        desc_src = av_pix_fmt_desc_get(srcFormat);
        desc_dst = av_pix_fmt_desc_get(dstFormat);
    
        if (!(unscaled && sws_isSupportedEndiannessConversion(srcFormat) &&
              av_pix_fmt_swap_endianness(srcFormat) == dstFormat)) {
    
        if (!sws_isSupportedInput(srcFormat)) {
    
            av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n",
    
                   av_get_pix_fmt_name(srcFormat));
    
        if (!sws_isSupportedOutput(dstFormat)) {
    
            av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n",
    
                   av_get_pix_fmt_name(dstFormat));
    
        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);
    
    
        /* provide a default scaler if not set by caller */
        if (!i) {
            if (dstW < srcW && dstH < srcH)
    
            else if (dstW > srcW && dstH > srcH)
    
            c->flags = flags;
        } else if (i & (i - 1)) {
    
            av_log(c, AV_LOG_ERROR,
    
                   "Exactly one scaler algorithm must be chosen, got %X\n", i);
    
        if (srcW < 1 || srcH < 1 || dstW < 1 || dstH < 1) {
    
            /* FIXME check if these are enough and try to lower them after
             * fixing the relevant parts of the code */
    
            av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",
    
        if (!dstFilter)
            dstFilter = &dummyFilter;
        if (!srcFilter)
            srcFilter = &dummyFilter;
    
        c->lumXInc      = (((int64_t)srcW << 16) + (dstW >> 1)) / dstW;
        c->lumYInc      = (((int64_t)srcH << 16) + (dstH >> 1)) / dstH;
    
        c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
        c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
    
        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);
    
        av_pix_fmt_get_chroma_sub_sample(srcFormat, &c->chrSrcHSubSample, &c->chrSrcVSubSample);
        av_pix_fmt_get_chroma_sub_sample(dstFormat, &c->chrDstHSubSample, &c->chrDstVSubSample);
    
        if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) {
            if (dstW&1) {
                av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n");
                flags |= SWS_FULL_CHR_H_INT;
                c->flags = flags;
    
    
            if (   c->chrSrcHSubSample == 0
                && c->chrSrcVSubSample == 0
                && c->dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER
                && !(c->flags & SWS_FAST_BILINEAR)
            ) {
                av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to input having non subsampled chroma\n");
                flags |= SWS_FULL_CHR_H_INT;
                c->flags = flags;
            }
    
        if (c->dither == SWS_DITHER_AUTO) {
            if (flags & SWS_ERROR_DIFFUSION)
                c->dither = SWS_DITHER_ED;
        }
    
    
        if(dstFormat == AV_PIX_FMT_BGR4_BYTE ||
           dstFormat == AV_PIX_FMT_RGB4_BYTE ||
           dstFormat == AV_PIX_FMT_BGR8 ||
           dstFormat == AV_PIX_FMT_RGB8) {
    
            if (c->dither == SWS_DITHER_AUTO)
                c->dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER;
    
            if (!(flags & SWS_FULL_CHR_H_INT)) {
    
                if (c->dither == SWS_DITHER_ED || c->dither == SWS_DITHER_A_DITHER || c->dither == SWS_DITHER_X_DITHER) {
    
                    av_log(c, AV_LOG_DEBUG,
                        "Desired dithering only supported in full chroma interpolation for destination format '%s'\n",
                        av_get_pix_fmt_name(dstFormat));
                    flags   |= SWS_FULL_CHR_H_INT;
                    c->flags = flags;
                }
    
            if (flags & SWS_FULL_CHR_H_INT) {
                if (c->dither == SWS_DITHER_BAYER) {
                    av_log(c, AV_LOG_DEBUG,
                        "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
                        av_get_pix_fmt_name(dstFormat));
                    c->dither = SWS_DITHER_ED;
                }
    
        if (isPlanarRGB(dstFormat)) {
    
            if (!(flags & SWS_FULL_CHR_H_INT)) {
                av_log(c, AV_LOG_DEBUG,
    
                       "%s output is not supported with half chroma resolution, switching to full\n",
                       av_get_pix_fmt_name(dstFormat));
    
                flags   |= SWS_FULL_CHR_H_INT;
                c->flags = flags;
            }
        }
    
        /* reuse chroma for 2 pixels RGB/BGR unless user wants full
         * chroma interpolation */
    
            isAnyRGB(dstFormat)        &&
    
            !isPlanarRGB(dstFormat)    &&
    
            dstFormat != AV_PIX_FMT_RGBA  &&
            dstFormat != AV_PIX_FMT_ARGB  &&
            dstFormat != AV_PIX_FMT_BGRA  &&
            dstFormat != AV_PIX_FMT_ABGR  &&
            dstFormat != AV_PIX_FMT_RGB24 &&
    
            dstFormat != AV_PIX_FMT_BGR24 &&
            dstFormat != AV_PIX_FMT_BGR4_BYTE &&
            dstFormat != AV_PIX_FMT_RGB4_BYTE &&
            dstFormat != AV_PIX_FMT_BGR8 &&
            dstFormat != AV_PIX_FMT_RGB8
        ) {
    
            av_log(c, AV_LOG_WARNING,
                   "full chroma interpolation for destination format '%s' not yet implemented\n",
    
                   av_get_pix_fmt_name(dstFormat));
    
            flags   &= ~SWS_FULL_CHR_H_INT;
    
        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 != AV_PIX_FMT_RGB8 && srcFormat != AV_PIX_FMT_BGR8 &&
            srcFormat != AV_PIX_FMT_RGB4 && srcFormat != AV_PIX_FMT_BGR4 &&
            srcFormat != AV_PIX_FMT_RGB4_BYTE && srcFormat != AV_PIX_FMT_BGR4_BYTE &&
    
            srcFormat != AV_PIX_FMT_GBRP9BE   && srcFormat != AV_PIX_FMT_GBRP9LE  &&
            srcFormat != AV_PIX_FMT_GBRP10BE  && srcFormat != AV_PIX_FMT_GBRP10LE &&
            srcFormat != AV_PIX_FMT_GBRP12BE  && srcFormat != AV_PIX_FMT_GBRP12LE &&
            srcFormat != AV_PIX_FMT_GBRP14BE  && srcFormat != AV_PIX_FMT_GBRP14LE &&
    
            srcFormat != AV_PIX_FMT_GBRP16BE  && srcFormat != AV_PIX_FMT_GBRP16LE &&
    
            ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) ||
             (flags & SWS_FAST_BILINEAR)))
            c->chrSrcHSubSample = 1;
    
        // Note the FF_CEIL_RSHIFT is so that we always round toward +inf.
        c->chrSrcW = FF_CEIL_RSHIFT(srcW, c->chrSrcHSubSample);
        c->chrSrcH = FF_CEIL_RSHIFT(srcH, c->chrSrcVSubSample);
        c->chrDstW = FF_CEIL_RSHIFT(dstW, c->chrDstHSubSample);
        c->chrDstH = FF_CEIL_RSHIFT(dstH, c->chrDstVSubSample);
    
        FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW*2+78, 16) * 2, fail);
    
    
        if (unscaled && !usesHFilter && !usesVFilter &&
            (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) {
    
                if (flags & SWS_PRINT_INFO)
                    av_log(c, AV_LOG_INFO,
                           "using unscaled %s -> %s special converter\n",
    
                           av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
    
        c->srcBpc = 1 + desc_src->comp[0].depth_minus1;
    
        if (c->srcBpc < 8)
            c->srcBpc = 8;
    
        c->dstBpc = 1 + desc_dst->comp[0].depth_minus1;
    
        if (c->dstBpc < 8)
            c->dstBpc = 8;
    
        if (isAnyRGB(srcFormat) || srcFormat == AV_PIX_FMT_PAL8)
    
            dst_stride <<= 1;
    
        if (INLINE_MMXEXT(cpu_flags) && c->srcBpc == 8 && c->dstBpc <= 14) {
    
            c->canMMXEXTBeUsed = dstW >= srcW && (dstW & 31) == 0 &&
    
                                 (srcW & 15) == 0;
    
            if (!c->canMMXEXTBeUsed && dstW >= srcW && c->chrDstW >= c->chrSrcW && (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 MMXEXT scaler\n");
    
            if (usesHFilter || isNBPS(c->srcFormat) || is16BPS(c->srcFormat) || isAnyRGB(c->srcFormat))
    
                c->canMMXEXTBeUsed = 0;
    
            c->canMMXEXTBeUsed = 0;
    
    
        c->chrXInc = (((int64_t)c->chrSrcW << 16) + (c->chrDstW >> 1)) / c->chrDstW;
        c->chrYInc = (((int64_t)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->canMMXEXTBeUsed) {
    
                c->lumXInc += 20;
                c->chrXInc += 20;
    
            // we don't use the x86 asm scaler if MMX is available
    
            else if (INLINE_MMX(cpu_flags) && c->dstBpc <= 14) {
    
                c->lumXInc = ((int64_t)(srcW       - 2) << 16) / (dstW       - 2) - 20;
                c->chrXInc = ((int64_t)(c->chrSrcW - 2) << 16) / (c->chrDstW - 2) - 20;
    
    #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS)
    
    
        /* precalculate horizontal scaler filter coefficients */
        {
    
    #if HAVE_MMXEXT_INLINE
    
            if (c->canMMXEXTBeUsed && (flags & SWS_FAST_BILINEAR)) {
    
                c->lumMmxextFilterCodeSize = init_hscaler_mmxext(dstW, c->lumXInc, NULL,
                                                                 NULL, NULL, 8);
                c->chrMmxextFilterCodeSize = init_hscaler_mmxext(c->chrDstW, c->chrXInc,
                                                                 NULL, NULL, NULL, 4);
    
                c->lumMmxextFilterCode = mmap(NULL, c->lumMmxextFilterCodeSize,
                                              PROT_READ | PROT_WRITE,
                                              MAP_PRIVATE | MAP_ANONYMOUS,
                                              -1, 0);
                c->chrMmxextFilterCode = mmap(NULL, c->chrMmxextFilterCodeSize,
                                              PROT_READ | PROT_WRITE,
                                              MAP_PRIVATE | MAP_ANONYMOUS,
                                              -1, 0);
    
                c->lumMmxextFilterCode = VirtualAlloc(NULL,
                                                      c->lumMmxextFilterCodeSize,
                                                      MEM_COMMIT,
                                                      PAGE_EXECUTE_READWRITE);
                c->chrMmxextFilterCode = VirtualAlloc(NULL,
                                                      c->chrMmxextFilterCodeSize,
                                                      MEM_COMMIT,
                                                      PAGE_EXECUTE_READWRITE);
    
                c->lumMmxextFilterCode = av_malloc(c->lumMmxextFilterCodeSize);
                c->chrMmxextFilterCode = av_malloc(c->chrMmxextFilterCodeSize);
    
    #ifdef MAP_ANONYMOUS
    
                if (c->lumMmxextFilterCode == MAP_FAILED || c->chrMmxextFilterCode == MAP_FAILED)
    
                if (!c->lumMmxextFilterCode || !c->chrMmxextFilterCode)
    
                {
                    av_log(c, AV_LOG_ERROR, "Failed to allocate MMX2FilterCode\n");
    
                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);
    
                init_hscaler_mmxext(      dstW, c->lumXInc, c->lumMmxextFilterCode,
                                    c->hLumFilter, (uint32_t*)c->hLumFilterPos, 8);
    
                init_hscaler_mmxext(c->chrDstW, c->chrXInc, c->chrMmxextFilterCode,
    
                                    c->hChrFilter, (uint32_t*)c->hChrFilterPos, 4);
    
                if (   mprotect(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize, PROT_EXEC | PROT_READ) == -1
                    || mprotect(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize, PROT_EXEC | PROT_READ) == -1) {
                    av_log(c, AV_LOG_ERROR, "mprotect failed, cannot use fast bilinear scaler\n");
                    goto fail;
                }
    
    #endif /* HAVE_MMXEXT_INLINE */
    
                const int filterAlign = X86_MMX(cpu_flags)     ? 4 :
                                        PPC_ALTIVEC(cpu_flags) ? 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,
                               get_local_pos(c, 0, 0, 0),
                               get_local_pos(c, 0, 0, 0)) < 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,
                               get_local_pos(c, c->chrSrcHSubSample, c->src_h_chr_pos, 0),
                               get_local_pos(c, c->chrDstHSubSample, c->dst_h_chr_pos, 0)) < 0)
    
                    goto fail;
            }
        } // initialize horizontal stuff
    
        /* precalculate vertical scaler filter coefficients */
        {
    
            const int filterAlign = X86_MMX(cpu_flags)     ? 2 :
                                    PPC_ALTIVEC(cpu_flags) ? 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,
                           get_local_pos(c, 0, 0, 1),
                           get_local_pos(c, 0, 0, 1)) < 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,
                           get_local_pos(c, c->chrSrcVSubSample, c->src_v_chr_pos, 1),
                           get_local_pos(c, c->chrDstVSubSample, c->dst_v_chr_pos, 1)) < 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];
    
        for (i = 0; i < 4; i++)
            FF_ALLOCZ_OR_GOTO(c, c->dither_error[i], (c->dstW+2) * sizeof(int), fail);
    
    
        /* 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->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
    
        c->uv_off   = (dst_stride>>1) + 64 / (c->dstBpc &~ 7);
    
        c->uv_offx2 = 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++)
    
            if(desc_dst->comp[0].depth_minus1 == 15){
    
                av_assert0(c->dstBpc > 14);
    
                for(j=0; j<dst_stride/2+1; j++)
                    ((int32_t*)(c->chrUPixBuf[i]))[j] = 1<<18;
            } else
                for(j=0; j<dst_stride+1; j++)
                    ((int16_t*)(c->chrUPixBuf[i]))[j] = 1<<14;
    
        av_assert0(c->chrDstH <= dstH);
    
        if (flags & SWS_PRINT_INFO) {
    
            const char *scaler = NULL, *cpucaps;
    
            for (i = 0; i < FF_ARRAY_ELEMS(scale_algorithms); i++) {
                if (flags & scale_algorithms[i].flag) {
                    scaler = scale_algorithms[i].description;
                    break;
                }
            }
            if (!scaler)
                scaler =  "ehh flags invalid?!";
            av_log(c, AV_LOG_INFO, "%s scaler, from %s to %s%s ",
    
                   av_get_pix_fmt_name(srcFormat),
    
                   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_get_pix_fmt_name(dstFormat));
    
            else if (INLINE_AMD3DNOW(cpu_flags))
    
                cpucaps = "C";
    
            av_log(c, AV_LOG_INFO, "using %s\n", cpucaps);
    
    
            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);
    
    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->srcFormat = srcFormat;
        c->dstFormat = dstFormat;
    
        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);
    
        SwsVector *vec;
    
        if(length <= 0 || length > INT_MAX/ sizeof(double))
            return NULL;
    
        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;
    
        if(variance < 0 || quality < 0)
            return NULL;
    
        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)
    {
    
        SwsVector *vec = sws_allocVec(a->length);
    
        memcpy(vec->coeff, a->coeff, a->length * sizeof(*a->coeff));
    
    
        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)
    {
    
        sws_freeVec(filter->lumH);
        sws_freeVec(filter->lumV);
        sws_freeVec(filter->chrH);
        sws_freeVec(filter->chrV);
    
        av_free(filter);
    }
    
    void sws_freeContext(SwsContext *c)
    {
        int i;