/* * Copyright (C) 2024 Niklas Haas * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #define _DEFAULT_SOURCE#define _SVID_SOURCE // needed for MAP_ANONYMOUS#define _DARWIN_C_SOURCE // needed for MAP_ANON#include <inttypes.h>#include <math.h>#include <stdio.h>#include <string.h>#if HAVE_MMAP#include <sys/mman.h>#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)#define MAP_ANONYMOUS MAP_ANON#endif#endif#if HAVE_VIRTUALALLOC#include <windows.h>#endif #include "libavutil/attributes.h"#include "libavutil/avassert.h"#include "libavutil/cpu.h"#include "libavutil/csp.h"#include "libavutil/emms.h"#include "libavutil/hdr_dynamic_metadata.h"#include "libavutil/imgutils.h"#include "libavutil/intreadwrite.h"#include "libavutil/libm.h"#include "libavutil/mastering_display_metadata.h"#include "libavutil/mathematics.h"#include "libavutil/mem.h"#include "libavutil/opt.h"#include "libavutil/pixdesc.h"#include "libavutil/slicethread.h"#include "libavutil/thread.h"#include "libavutil/aarch64/cpu.h"#include "libavutil/ppc/cpu.h"#include "libavutil/x86/asm.h"#include "libavutil/x86/cpu.h"#include "libavutil/loongarch/cpu.h" #include "rgb2rgb.h"#include "swscale.h"#include "swscale_internal.h"#include "utils.h"#include "graph.h" typedef struct FormatEntry { uint8_t is_supported_in :1; uint8_t is_supported_out :1; uint8_t is_supported_endianness :1;} FormatEntry; static const FormatEntry format_entries[] = { [AV_PIX_FMT_YUV420P] = { 1, 1 }, [AV_PIX_FMT_YUYV422] = { 1, 1 }, [AV_PIX_FMT_RGB24] = { 1, 1 }, [AV_PIX_FMT_BGR24] = { 1, 1 }, [AV_PIX_FMT_YUV422P] = { 1, 1 }, [AV_PIX_FMT_YUV444P] = { 1, 1 }, [AV_PIX_FMT_YUV410P] = { 1, 1 }, [AV_PIX_FMT_YUV411P] = { 1, 1 }, [AV_PIX_FMT_GRAY8] = { 1, 1 }, [AV_PIX_FMT_MONOWHITE] = { 1, 1 }, [AV_PIX_FMT_MONOBLACK] = { 1, 1 }, [AV_PIX_FMT_PAL8] = { 1, 0 }, [AV_PIX_FMT_YUVJ420P] = { 1, 1 }, [AV_PIX_FMT_YUVJ411P] = { 1, 1 }, [AV_PIX_FMT_YUVJ422P] = { 1, 1 }, [AV_PIX_FMT_YUVJ444P] = { 1, 1 }, [AV_PIX_FMT_YVYU422] = { 1, 1 }, [AV_PIX_FMT_UYVY422] = { 1, 1 }, [AV_PIX_FMT_UYYVYY411] = { 0, 0 }, [AV_PIX_FMT_BGR8] = { 1, 1 }, [AV_PIX_FMT_BGR4] = { 0, 1 }, [AV_PIX_FMT_BGR4_BYTE] = { 1, 1 }, [AV_PIX_FMT_RGB8] = { 1, 1 }, [AV_PIX_FMT_RGB4] = { 0, 1 }, [AV_PIX_FMT_RGB4_BYTE] = { 1, 1 }, [AV_PIX_FMT_NV12] = { 1, 1 }, [AV_PIX_FMT_NV21] = { 1, 1 }, [AV_PIX_FMT_ARGB] = { 1, 1 }, [AV_PIX_FMT_RGBA] = { 1, 1 }, [AV_PIX_FMT_ABGR] = { 1, 1 }, [AV_PIX_FMT_BGRA] = { 1, 1 }, [AV_PIX_FMT_0RGB] = { 1, 1 }, [AV_PIX_FMT_RGB0] = { 1, 1 }, [AV_PIX_FMT_0BGR] = { 1, 1 }, [AV_PIX_FMT_BGR0] = { 1, 1 }, [AV_PIX_FMT_GRAY9BE] = { 1, 1 }, [AV_PIX_FMT_GRAY9LE] = { 1, 1 }, [AV_PIX_FMT_GRAY10BE] = { 1, 1 }, [AV_PIX_FMT_GRAY10LE] = { 1, 1 }, [AV_PIX_FMT_GRAY12BE] = { 1, 1 }, [AV_PIX_FMT_GRAY12LE] = { 1, 1 }, [AV_PIX_FMT_GRAY14BE] = { 1, 1 }, [AV_PIX_FMT_GRAY14LE] = { 1, 1 }, [AV_PIX_FMT_GRAY16BE] = { 1, 1 }, [AV_PIX_FMT_GRAY16LE] = { 1, 1 }, [AV_PIX_FMT_YUV440P] = { 1, 1 }, [AV_PIX_FMT_YUVJ440P] = { 1, 1 }, [AV_PIX_FMT_YUV440P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV440P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV440P12LE] = { 1, 1 }, [AV_PIX_FMT_YUV440P12BE] = { 1, 1 }, [AV_PIX_FMT_YUVA420P] = { 1, 1 }, [AV_PIX_FMT_YUVA422P] = { 1, 1 }, [AV_PIX_FMT_YUVA444P] = { 1, 1 }, [AV_PIX_FMT_YUVA420P9BE] = { 1, 1 }, [AV_PIX_FMT_YUVA420P9LE] = { 1, 1 }, [AV_PIX_FMT_YUVA422P9BE] = { 1, 1 }, [AV_PIX_FMT_YUVA422P9LE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P9BE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P9LE] = { 1, 1 }, [AV_PIX_FMT_YUVA420P10BE]= { 1, 1 }, [AV_PIX_FMT_YUVA420P10LE]= { 1, 1 }, [AV_PIX_FMT_YUVA422P10BE]= { 1, 1 }, [AV_PIX_FMT_YUVA422P10LE]= { 1, 1 }, [AV_PIX_FMT_YUVA444P10BE]= { 1, 1 }, [AV_PIX_FMT_YUVA444P10LE]= { 1, 1 }, [AV_PIX_FMT_YUVA420P16BE]= { 1, 1 }, [AV_PIX_FMT_YUVA420P16LE]= { 1, 1 }, [AV_PIX_FMT_YUVA422P16BE]= { 1, 1 }, [AV_PIX_FMT_YUVA422P16LE]= { 1, 1 }, [AV_PIX_FMT_YUVA444P16BE]= { 1, 1 }, [AV_PIX_FMT_YUVA444P16LE]= { 1, 1 }, [AV_PIX_FMT_RGB48BE] = { 1, 1 }, [AV_PIX_FMT_RGB48LE] = { 1, 1 }, [AV_PIX_FMT_RGBA64BE] = { 1, 1, 1 }, [AV_PIX_FMT_RGBA64LE] = { 1, 1, 1 }, [AV_PIX_FMT_RGB565BE] = { 1, 1 }, [AV_PIX_FMT_RGB565LE] = { 1, 1 }, [AV_PIX_FMT_RGB555BE] = { 1, 1 }, [AV_PIX_FMT_RGB555LE] = { 1, 1 }, [AV_PIX_FMT_BGR565BE] = { 1, 1 }, [AV_PIX_FMT_BGR565LE] = { 1, 1 }, [AV_PIX_FMT_BGR555BE] = { 1, 1 }, [AV_PIX_FMT_BGR555LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P16LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P16BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P16LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P16BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P16LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P16BE] = { 1, 1 }, [AV_PIX_FMT_RGB444LE] = { 1, 1 }, [AV_PIX_FMT_RGB444BE] = { 1, 1 }, [AV_PIX_FMT_BGR444LE] = { 1, 1 }, [AV_PIX_FMT_BGR444BE] = { 1, 1 }, [AV_PIX_FMT_YA8] = { 1, 1 }, [AV_PIX_FMT_YA16BE] = { 1, 1 }, [AV_PIX_FMT_YA16LE] = { 1, 1 }, [AV_PIX_FMT_BGR48BE] = { 1, 1 }, [AV_PIX_FMT_BGR48LE] = { 1, 1 }, [AV_PIX_FMT_BGRA64BE] = { 1, 1, 1 }, [AV_PIX_FMT_BGRA64LE] = { 1, 1, 1 }, [AV_PIX_FMT_YUV420P9BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P9LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P12BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P12LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P14BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P14LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P9BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P9LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P12BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P12LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P14BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P14LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P9BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P9LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P12BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P12LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P14BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P14LE] = { 1, 1 }, [AV_PIX_FMT_GBRP] = { 1, 1 }, [AV_PIX_FMT_GBRP9LE] = { 1, 1 }, [AV_PIX_FMT_GBRP9BE] = { 1, 1 }, [AV_PIX_FMT_GBRP10LE] = { 1, 1 }, [AV_PIX_FMT_GBRP10BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP10LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP10BE] = { 1, 1 }, [AV_PIX_FMT_GBRP12LE] = { 1, 1 }, [AV_PIX_FMT_GBRP12BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP12LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP12BE] = { 1, 1 }, [AV_PIX_FMT_GBRP14LE] = { 1, 1 }, [AV_PIX_FMT_GBRP14BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP14LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP14BE] = { 1, 1 }, [AV_PIX_FMT_GBRP16LE] = { 1, 1 }, [AV_PIX_FMT_GBRP16BE] = { 1, 1 }, [AV_PIX_FMT_GBRPF32LE] = { 1, 1 }, [AV_PIX_FMT_GBRPF32BE] = { 1, 1 }, [AV_PIX_FMT_GBRAPF32LE] = { 1, 1 }, [AV_PIX_FMT_GBRAPF32BE] = { 1, 1 }, [AV_PIX_FMT_GBRPF16LE] = { 1, 0 }, [AV_PIX_FMT_GBRPF16BE] = { 1, 0 }, [AV_PIX_FMT_GBRAPF16LE] = { 1, 0 }, [AV_PIX_FMT_GBRAPF16BE] = { 1, 0 }, [AV_PIX_FMT_GBRAP] = { 1, 1 }, [AV_PIX_FMT_GBRAP16LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP16BE] = { 1, 1 }, [AV_PIX_FMT_BAYER_BGGR8] = { 1, 0 }, [AV_PIX_FMT_BAYER_RGGB8] = { 1, 0 }, [AV_PIX_FMT_BAYER_GBRG8] = { 1, 0 }, [AV_PIX_FMT_BAYER_GRBG8] = { 1, 0 }, [AV_PIX_FMT_BAYER_BGGR16LE] = { 1, 0 }, [AV_PIX_FMT_BAYER_BGGR16BE] = { 1, 0 }, [AV_PIX_FMT_BAYER_RGGB16LE] = { 1, 0 }, [AV_PIX_FMT_BAYER_RGGB16BE] = { 1, 0 }, [AV_PIX_FMT_BAYER_GBRG16LE] = { 1, 0 }, [AV_PIX_FMT_BAYER_GBRG16BE] = { 1, 0 }, [AV_PIX_FMT_BAYER_GRBG16LE] = { 1, 0 }, [AV_PIX_FMT_BAYER_GRBG16BE] = { 1, 0 }, [AV_PIX_FMT_XYZ12BE] = { 1, 1, 1 }, [AV_PIX_FMT_XYZ12LE] = { 1, 1, 1 }, [AV_PIX_FMT_AYUV64LE] = { 1, 1}, [AV_PIX_FMT_AYUV64BE] = { 1, 1 }, [AV_PIX_FMT_P010LE] = { 1, 1 }, [AV_PIX_FMT_P010BE] = { 1, 1 }, [AV_PIX_FMT_P012LE] = { 1, 1 }, [AV_PIX_FMT_P012BE] = { 1, 1 }, [AV_PIX_FMT_P016LE] = { 1, 1 }, [AV_PIX_FMT_P016BE] = { 1, 1 }, [AV_PIX_FMT_GRAYF32LE] = { 1, 1 }, [AV_PIX_FMT_GRAYF32BE] = { 1, 1 }, [AV_PIX_FMT_GRAYF16LE] = { 1, 0 }, [AV_PIX_FMT_GRAYF16BE] = { 1, 0 }, [AV_PIX_FMT_YUVA422P12BE] = { 1, 1 }, [AV_PIX_FMT_YUVA422P12LE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P12BE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P12LE] = { 1, 1 }, [AV_PIX_FMT_NV24] = { 1, 1 }, [AV_PIX_FMT_NV42] = { 1, 1 }, [AV_PIX_FMT_Y210LE] = { 1, 1 }, [AV_PIX_FMT_Y212LE] = { 1, 1 }, [AV_PIX_FMT_Y216LE] = { 1, 1 }, [AV_PIX_FMT_X2RGB10LE] = { 1, 1 }, [AV_PIX_FMT_X2BGR10LE] = { 1, 1 }, [AV_PIX_FMT_P210BE] = { 1, 1 }, [AV_PIX_FMT_P210LE] = { 1, 1 }, [AV_PIX_FMT_P212BE] = { 1, 1 }, [AV_PIX_FMT_P212LE] = { 1, 1 }, [AV_PIX_FMT_P410BE] = { 1, 1 }, [AV_PIX_FMT_P410LE] = { 1, 1 }, [AV_PIX_FMT_P412BE] = { 1, 1 }, [AV_PIX_FMT_P412LE] = { 1, 1 }, [AV_PIX_FMT_P216BE] = { 1, 1 }, [AV_PIX_FMT_P216LE] = { 1, 1 }, [AV_PIX_FMT_P416BE] = { 1, 1 }, [AV_PIX_FMT_P416LE] = { 1, 1 }, [AV_PIX_FMT_NV16] = { 1, 1 }, [AV_PIX_FMT_VUYA] = { 1, 1 }, [AV_PIX_FMT_VUYX] = { 1, 1 }, [AV_PIX_FMT_RGBAF16BE] = { 1, 0 }, [AV_PIX_FMT_RGBAF16LE] = { 1, 0 }, [AV_PIX_FMT_RGBF16BE] = { 1, 0 }, [AV_PIX_FMT_RGBF16LE] = { 1, 0 }, [AV_PIX_FMT_RGBF32BE] = { 1, 0 }, [AV_PIX_FMT_RGBF32LE] = { 1, 0 }, [AV_PIX_FMT_XV30LE] = { 1, 1 }, [AV_PIX_FMT_XV36LE] = { 1, 1 }, [AV_PIX_FMT_XV36BE] = { 1, 1 }, [AV_PIX_FMT_XV48LE] = { 1, 1 }, [AV_PIX_FMT_XV48BE] = { 1, 1 }, [AV_PIX_FMT_AYUV] = { 1, 1 }, [AV_PIX_FMT_UYVA] = { 1, 1 }, [AV_PIX_FMT_VYU444] = { 1, 1 }, [AV_PIX_FMT_V30XLE] = { 1, 1 },}; /** * Allocate and return an SwsContext without performing initialization. */static SwsContext *alloc_set_opts(int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, const double *param){ SwsContext *sws = sws_alloc_context(); if (!sws) return NULL; sws->flags = flags; sws->src_w = srcW; sws->src_h = srcH; sws->dst_w = dstW; sws->dst_h = dstH; sws->src_format = srcFormat; sws->dst_format = dstFormat; if (param) { sws->scaler_params[0] = param[0]; sws->scaler_params[1] = param[1]; } return sws;} int ff_shuffle_filter_coefficients(SwsInternal *c, int *filterPos, int filterSize, int16_t *filter, int dstW){#if ARCH_X86_64 int i, j, k; int cpu_flags = av_get_cpu_flags(); if (!filter) return 0; if (EXTERNAL_AVX2_FAST(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) { if ((c->srcBpc == 8) && (c->dstBpc <= 14)) { int16_t *filterCopy = NULL; if (filterSize > 4) { if (!FF_ALLOC_TYPED_ARRAY(filterCopy, dstW * filterSize)) return AVERROR(ENOMEM); memcpy(filterCopy, filter, dstW * filterSize * sizeof(int16_t)); } // Do not swap filterPos for pixels which won't be processed by // the main loop. for (i = 0; i + 16 <= dstW; i += 16) { FFSWAP(int, filterPos[i + 2], filterPos[i + 4]); FFSWAP(int, filterPos[i + 3], filterPos[i + 5]); FFSWAP(int, filterPos[i + 10], filterPos[i + 12]); FFSWAP(int, filterPos[i + 11], filterPos[i + 13]); } if (filterSize > 4) { // 16 pixels are processed at a time. for (i = 0; i + 16 <= dstW; i += 16) { // 4 filter coeffs are processed at a time. for (k = 0; k + 4 <= filterSize; k += 4) { for (j = 0; j < 16; ++j) { int from = (i + j) * filterSize + k; int to = i * filterSize + j * 4 + k * 16; memcpy(&filter[to], &filterCopy[from], 4 * sizeof(int16_t)); } } } // 4 pixels are processed at a time in the tail. for (; i < dstW; i += 4) { // 4 filter coeffs are processed at a time. int rem = dstW - i >= 4 ? 4 : dstW - i; for (k = 0; k + 4 <= filterSize; k += 4) { for (j = 0; j < rem; ++j) { int from = (i + j) * filterSize + k; int to = i * filterSize + j * 4 + k * 4; memcpy(&filter[to], &filterCopy[from], 4 * sizeof(int16_t)); } } } } av_free(filterCopy); } }#endif return 0;} int sws_isSupportedInput(enum AVPixelFormat pix_fmt){ return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_in : 0;} int sws_isSupportedOutput(enum AVPixelFormat pix_fmt){ return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_out : 0;} int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt){ return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_endianness : 0;} static double getSplineCoeff(double a, double b, double c, double d, double dist){ if (dist <= 1.0) return ((d * dist + c) * dist + b) * dist + a; else return getSplineCoeff(0.0, b + 2.0 * c + 3.0 * d, c + 3.0 * d, -b - 3.0 * c - 6.0 * d, dist - 1.0);} static av_cold int get_local_pos(SwsInternal *s, int chr_subsample, int pos, int dir){ if (pos == -1 || pos <= -513) { pos = (128 << chr_subsample) - 128; } pos += 128; // relative to ideal left edge return pos >> chr_subsample;} typedef struct { int flag; ///< flag associated to the algorithm const char *description; ///< human-readable description int size_factor; ///< size factor used when initing the filters} ScaleAlgorithm; static const ScaleAlgorithm scale_algorithms[] = { { SWS_AREA, "area averaging", 1 /* downscale only, for upscale it is bilinear */ }, { SWS_BICUBIC, "bicubic", 4 }, { SWS_BICUBLIN, "luma bicubic / chroma bilinear", -1 }, { SWS_BILINEAR, "bilinear", 2 }, { SWS_FAST_BILINEAR, "fast bilinear", -1 }, { SWS_GAUSS, "Gaussian", 8 /* infinite ;) */ }, { SWS_LANCZOS, "Lanczos", -1 /* custom */ }, { SWS_POINT, "nearest neighbor / point", -1 }, { SWS_SINC, "sinc", 20 /* infinite ;) */ }, { SWS_SPLINE, "bicubic spline", 20 /* infinite :)*/ }, { SWS_X, "experimental", 8 },}; static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, int *outFilterSize, int xInc, int srcW, int dstW, int filterAlign, int one, int flags, int cpu_flags, SwsVector *srcFilter, SwsVector *dstFilter, double param[2], int srcPos, int dstPos){ int i; int filterSize; int filter2Size; int minFilterSize; int64_t *filter = NULL; int64_t *filter2 = NULL; const int64_t fone = 1LL << (54 - FFMIN(av_log2(srcW/dstW), 8)); int ret = -1; emms_c(); // FIXME should not be required but IS (even for non-MMX versions) // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end if (!FF_ALLOC_TYPED_ARRAY(*filterPos, dstW + 3)) goto nomem; if (FFABS(xInc - 0x10000) < 10 && srcPos == dstPos) { // unscaled int i; filterSize = 1; if (!FF_ALLOCZ_TYPED_ARRAY(filter, dstW * filterSize)) goto nomem; for (i = 0; i < dstW; i++) { filter[i * filterSize] = fone; (*filterPos)[i] = i; } } else if (flags & SWS_POINT) { // lame looking point sampling mode int i; int64_t xDstInSrc; filterSize = 1; if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize)) goto nomem; xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); for (i = 0; i < dstW; i++) { int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16; (*filterPos)[i] = xx; filter[i] = fone; xDstInSrc += xInc; } } else if ((xInc <= (1 << 16) && (flags & SWS_AREA)) || (flags & SWS_FAST_BILINEAR)) { // bilinear upscale int i; int64_t xDstInSrc; filterSize = 2; if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize)) goto nomem; xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); for (i = 0; i < dstW; i++) { int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16; int j;Lines 1–500 of 2991. Load more
/* * Copyright (C) 2024 Niklas Haas * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #define _DEFAULT_SOURCE #define _SVID_SOURCE // needed for MAP_ANONYMOUS #define _DARWIN_C_SOURCE // needed for MAP_ANON #include <inttypes.h> #include <math.h> #include <stdio.h> #include <string.h> #if HAVE_MMAP #include <sys/mman.h> #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON #endif #endif #if HAVE_VIRTUALALLOC #include <windows.h> #endif #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/cpu.h" #include "libavutil/csp.h" #include "libavutil/emms.h" #include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavutil/libm.h" #include "libavutil/mastering_display_metadata.h" #include "libavutil/mathematics.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/slicethread.h" #include "libavutil/thread.h" #include "libavutil/aarch64/cpu.h" #include "libavutil/ppc/cpu.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavutil/loongarch/cpu.h" #include "rgb2rgb.h" #include "swscale.h" #include "swscale_internal.h" #include "utils.h" #include "graph.h" typedef struct FormatEntry { uint8_t is_supported_in :1; uint8_t is_supported_out :1; uint8_t is_supported_endianness :1; } FormatEntry; static const FormatEntry format_entries[] = { [AV_PIX_FMT_YUV420P] = { 1, 1 }, [AV_PIX_FMT_YUYV422] = { 1, 1 }, [AV_PIX_FMT_RGB24] = { 1, 1 }, [AV_PIX_FMT_BGR24] = { 1, 1 }, [AV_PIX_FMT_YUV422P] = { 1, 1 }, [AV_PIX_FMT_YUV444P] = { 1, 1 }, [AV_PIX_FMT_YUV410P] = { 1, 1 }, [AV_PIX_FMT_YUV411P] = { 1, 1 }, [AV_PIX_FMT_GRAY8] = { 1, 1 }, [AV_PIX_FMT_MONOWHITE] = { 1, 1 }, [AV_PIX_FMT_MONOBLACK] = { 1, 1 }, [AV_PIX_FMT_PAL8] = { 1, 0 }, [AV_PIX_FMT_YUVJ420P] = { 1, 1 }, [AV_PIX_FMT_YUVJ411P] = { 1, 1 }, [AV_PIX_FMT_YUVJ422P] = { 1, 1 }, [AV_PIX_FMT_YUVJ444P] = { 1, 1 }, [AV_PIX_FMT_YVYU422] = { 1, 1 }, [AV_PIX_FMT_UYVY422] = { 1, 1 }, [AV_PIX_FMT_UYYVYY411] = { 0, 0 }, [AV_PIX_FMT_BGR8] = { 1, 1 }, [AV_PIX_FMT_BGR4] = { 0, 1 }, [AV_PIX_FMT_BGR4_BYTE] = { 1, 1 }, [AV_PIX_FMT_RGB8] = { 1, 1 }, [AV_PIX_FMT_RGB4] = { 0, 1 }, [AV_PIX_FMT_RGB4_BYTE] = { 1, 1 }, [AV_PIX_FMT_NV12] = { 1, 1 }, [AV_PIX_FMT_NV21] = { 1, 1 }, [AV_PIX_FMT_ARGB] = { 1, 1 }, [AV_PIX_FMT_RGBA] = { 1, 1 }, [AV_PIX_FMT_ABGR] = { 1, 1 }, [AV_PIX_FMT_BGRA] = { 1, 1 }, [AV_PIX_FMT_0RGB] = { 1, 1 }, [AV_PIX_FMT_RGB0] = { 1, 1 }, [AV_PIX_FMT_0BGR] = { 1, 1 }, [AV_PIX_FMT_BGR0] = { 1, 1 }, [AV_PIX_FMT_GRAY9BE] = { 1, 1 }, [AV_PIX_FMT_GRAY9LE] = { 1, 1 }, [AV_PIX_FMT_GRAY10BE] = { 1, 1 }, [AV_PIX_FMT_GRAY10LE] = { 1, 1 }, [AV_PIX_FMT_GRAY12BE] = { 1, 1 }, [AV_PIX_FMT_GRAY12LE] = { 1, 1 }, [AV_PIX_FMT_GRAY14BE] = { 1, 1 }, [AV_PIX_FMT_GRAY14LE] = { 1, 1 }, [AV_PIX_FMT_GRAY16BE] = { 1, 1 }, [AV_PIX_FMT_GRAY16LE] = { 1, 1 }, [AV_PIX_FMT_YUV440P] = { 1, 1 }, [AV_PIX_FMT_YUVJ440P] = { 1, 1 }, [AV_PIX_FMT_YUV440P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV440P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV440P12LE] = { 1, 1 }, [AV_PIX_FMT_YUV440P12BE] = { 1, 1 }, [AV_PIX_FMT_YUVA420P] = { 1, 1 }, [AV_PIX_FMT_YUVA422P] = { 1, 1 }, [AV_PIX_FMT_YUVA444P] = { 1, 1 }, [AV_PIX_FMT_YUVA420P9BE] = { 1, 1 }, [AV_PIX_FMT_YUVA420P9LE] = { 1, 1 }, [AV_PIX_FMT_YUVA422P9BE] = { 1, 1 }, [AV_PIX_FMT_YUVA422P9LE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P9BE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P9LE] = { 1, 1 }, [AV_PIX_FMT_YUVA420P10BE]= { 1, 1 }, [AV_PIX_FMT_YUVA420P10LE]= { 1, 1 }, [AV_PIX_FMT_YUVA422P10BE]= { 1, 1 }, [AV_PIX_FMT_YUVA422P10LE]= { 1, 1 }, [AV_PIX_FMT_YUVA444P10BE]= { 1, 1 }, [AV_PIX_FMT_YUVA444P10LE]= { 1, 1 }, [AV_PIX_FMT_YUVA420P16BE]= { 1, 1 }, [AV_PIX_FMT_YUVA420P16LE]= { 1, 1 }, [AV_PIX_FMT_YUVA422P16BE]= { 1, 1 }, [AV_PIX_FMT_YUVA422P16LE]= { 1, 1 }, [AV_PIX_FMT_YUVA444P16BE]= { 1, 1 }, [AV_PIX_FMT_YUVA444P16LE]= { 1, 1 }, [AV_PIX_FMT_RGB48BE] = { 1, 1 }, [AV_PIX_FMT_RGB48LE] = { 1, 1 }, [AV_PIX_FMT_RGBA64BE] = { 1, 1, 1 }, [AV_PIX_FMT_RGBA64LE] = { 1, 1, 1 }, [AV_PIX_FMT_RGB565BE] = { 1, 1 }, [AV_PIX_FMT_RGB565LE] = { 1, 1 }, [AV_PIX_FMT_RGB555BE] = { 1, 1 }, [AV_PIX_FMT_RGB555LE] = { 1, 1 }, [AV_PIX_FMT_BGR565BE] = { 1, 1 }, [AV_PIX_FMT_BGR565LE] = { 1, 1 }, [AV_PIX_FMT_BGR555BE] = { 1, 1 }, [AV_PIX_FMT_BGR555LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P16LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P16BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P16LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P16BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P16LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P16BE] = { 1, 1 }, [AV_PIX_FMT_RGB444LE] = { 1, 1 }, [AV_PIX_FMT_RGB444BE] = { 1, 1 }, [AV_PIX_FMT_BGR444LE] = { 1, 1 }, [AV_PIX_FMT_BGR444BE] = { 1, 1 }, [AV_PIX_FMT_YA8] = { 1, 1 }, [AV_PIX_FMT_YA16BE] = { 1, 1 }, [AV_PIX_FMT_YA16LE] = { 1, 1 }, [AV_PIX_FMT_BGR48BE] = { 1, 1 }, [AV_PIX_FMT_BGR48LE] = { 1, 1 }, [AV_PIX_FMT_BGRA64BE] = { 1, 1, 1 }, [AV_PIX_FMT_BGRA64LE] = { 1, 1, 1 }, [AV_PIX_FMT_YUV420P9BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P9LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P12BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P12LE] = { 1, 1 }, [AV_PIX_FMT_YUV420P14BE] = { 1, 1 }, [AV_PIX_FMT_YUV420P14LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P9BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P9LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P12BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P12LE] = { 1, 1 }, [AV_PIX_FMT_YUV422P14BE] = { 1, 1 }, [AV_PIX_FMT_YUV422P14LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P9BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P9LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P10BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P10LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P12BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P12LE] = { 1, 1 }, [AV_PIX_FMT_YUV444P14BE] = { 1, 1 }, [AV_PIX_FMT_YUV444P14LE] = { 1, 1 }, [AV_PIX_FMT_GBRP] = { 1, 1 }, [AV_PIX_FMT_GBRP9LE] = { 1, 1 }, [AV_PIX_FMT_GBRP9BE] = { 1, 1 }, [AV_PIX_FMT_GBRP10LE] = { 1, 1 }, [AV_PIX_FMT_GBRP10BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP10LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP10BE] = { 1, 1 }, [AV_PIX_FMT_GBRP12LE] = { 1, 1 }, [AV_PIX_FMT_GBRP12BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP12LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP12BE] = { 1, 1 }, [AV_PIX_FMT_GBRP14LE] = { 1, 1 }, [AV_PIX_FMT_GBRP14BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP14LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP14BE] = { 1, 1 }, [AV_PIX_FMT_GBRP16LE] = { 1, 1 }, [AV_PIX_FMT_GBRP16BE] = { 1, 1 }, [AV_PIX_FMT_GBRPF32LE] = { 1, 1 }, [AV_PIX_FMT_GBRPF32BE] = { 1, 1 }, [AV_PIX_FMT_GBRAPF32LE] = { 1, 1 }, [AV_PIX_FMT_GBRAPF32BE] = { 1, 1 }, [AV_PIX_FMT_GBRPF16LE] = { 1, 0 }, [AV_PIX_FMT_GBRPF16BE] = { 1, 0 }, [AV_PIX_FMT_GBRAPF16LE] = { 1, 0 }, [AV_PIX_FMT_GBRAPF16BE] = { 1, 0 }, [AV_PIX_FMT_GBRAP] = { 1, 1 }, [AV_PIX_FMT_GBRAP16LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP16BE] = { 1, 1 }, [AV_PIX_FMT_BAYER_BGGR8] = { 1, 0 }, [AV_PIX_FMT_BAYER_RGGB8] = { 1, 0 }, [AV_PIX_FMT_BAYER_GBRG8] = { 1, 0 }, [AV_PIX_FMT_BAYER_GRBG8] = { 1, 0 }, [AV_PIX_FMT_BAYER_BGGR16LE] = { 1, 0 }, [AV_PIX_FMT_BAYER_BGGR16BE] = { 1, 0 }, [AV_PIX_FMT_BAYER_RGGB16LE] = { 1, 0 }, [AV_PIX_FMT_BAYER_RGGB16BE] = { 1, 0 }, [AV_PIX_FMT_BAYER_GBRG16LE] = { 1, 0 }, [AV_PIX_FMT_BAYER_GBRG16BE] = { 1, 0 }, [AV_PIX_FMT_BAYER_GRBG16LE] = { 1, 0 }, [AV_PIX_FMT_BAYER_GRBG16BE] = { 1, 0 }, [AV_PIX_FMT_XYZ12BE] = { 1, 1, 1 }, [AV_PIX_FMT_XYZ12LE] = { 1, 1, 1 }, [AV_PIX_FMT_AYUV64LE] = { 1, 1}, [AV_PIX_FMT_AYUV64BE] = { 1, 1 }, [AV_PIX_FMT_P010LE] = { 1, 1 }, [AV_PIX_FMT_P010BE] = { 1, 1 }, [AV_PIX_FMT_P012LE] = { 1, 1 }, [AV_PIX_FMT_P012BE] = { 1, 1 }, [AV_PIX_FMT_P016LE] = { 1, 1 }, [AV_PIX_FMT_P016BE] = { 1, 1 }, [AV_PIX_FMT_GRAYF32LE] = { 1, 1 }, [AV_PIX_FMT_GRAYF32BE] = { 1, 1 }, [AV_PIX_FMT_GRAYF16LE] = { 1, 0 }, [AV_PIX_FMT_GRAYF16BE] = { 1, 0 }, [AV_PIX_FMT_YUVA422P12BE] = { 1, 1 }, [AV_PIX_FMT_YUVA422P12LE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P12BE] = { 1, 1 }, [AV_PIX_FMT_YUVA444P12LE] = { 1, 1 }, [AV_PIX_FMT_NV24] = { 1, 1 }, [AV_PIX_FMT_NV42] = { 1, 1 }, [AV_PIX_FMT_Y210LE] = { 1, 1 }, [AV_PIX_FMT_Y212LE] = { 1, 1 }, [AV_PIX_FMT_Y216LE] = { 1, 1 }, [AV_PIX_FMT_X2RGB10LE] = { 1, 1 }, [AV_PIX_FMT_X2BGR10LE] = { 1, 1 }, [AV_PIX_FMT_P210BE] = { 1, 1 }, [AV_PIX_FMT_P210LE] = { 1, 1 }, [AV_PIX_FMT_P212BE] = { 1, 1 }, [AV_PIX_FMT_P212LE] = { 1, 1 }, [AV_PIX_FMT_P410BE] = { 1, 1 }, [AV_PIX_FMT_P410LE] = { 1, 1 }, [AV_PIX_FMT_P412BE] = { 1, 1 }, [AV_PIX_FMT_P412LE] = { 1, 1 }, [AV_PIX_FMT_P216BE] = { 1, 1 }, [AV_PIX_FMT_P216LE] = { 1, 1 }, [AV_PIX_FMT_P416BE] = { 1, 1 }, [AV_PIX_FMT_P416LE] = { 1, 1 }, [AV_PIX_FMT_NV16] = { 1, 1 }, [AV_PIX_FMT_VUYA] = { 1, 1 }, [AV_PIX_FMT_VUYX] = { 1, 1 }, [AV_PIX_FMT_RGBAF16BE] = { 1, 0 }, [AV_PIX_FMT_RGBAF16LE] = { 1, 0 }, [AV_PIX_FMT_RGBF16BE] = { 1, 0 }, [AV_PIX_FMT_RGBF16LE] = { 1, 0 }, [AV_PIX_FMT_RGBF32BE] = { 1, 0 }, [AV_PIX_FMT_RGBF32LE] = { 1, 0 }, [AV_PIX_FMT_XV30LE] = { 1, 1 }, [AV_PIX_FMT_XV36LE] = { 1, 1 }, [AV_PIX_FMT_XV36BE] = { 1, 1 }, [AV_PIX_FMT_XV48LE] = { 1, 1 }, [AV_PIX_FMT_XV48BE] = { 1, 1 }, [AV_PIX_FMT_AYUV] = { 1, 1 }, [AV_PIX_FMT_UYVA] = { 1, 1 }, [AV_PIX_FMT_VYU444] = { 1, 1 }, [AV_PIX_FMT_V30XLE] = { 1, 1 }, }; /** * Allocate and return an SwsContext without performing initialization. */ static SwsContext *alloc_set_opts(int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, const double *param) { SwsContext *sws = sws_alloc_context(); if (!sws) return NULL; sws->flags = flags; sws->src_w = srcW; sws->src_h = srcH; sws->dst_w = dstW; sws->dst_h = dstH; sws->src_format = srcFormat; sws->dst_format = dstFormat; if (param) { sws->scaler_params[0] = param[0]; sws->scaler_params[1] = param[1]; } return sws; } int ff_shuffle_filter_coefficients(SwsInternal *c, int *filterPos, int filterSize, int16_t *filter, int dstW) { #if ARCH_X86_64 int i, j, k; int cpu_flags = av_get_cpu_flags(); if (!filter) return 0; if (EXTERNAL_AVX2_FAST(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) { if ((c->srcBpc == 8) && (c->dstBpc <= 14)) { int16_t *filterCopy = NULL; if (filterSize > 4) { if (!FF_ALLOC_TYPED_ARRAY(filterCopy, dstW * filterSize)) return AVERROR(ENOMEM); memcpy(filterCopy, filter, dstW * filterSize * sizeof(int16_t)); } // Do not swap filterPos for pixels which won't be processed by // the main loop. for (i = 0; i + 16 <= dstW; i += 16) { FFSWAP(int, filterPos[i + 2], filterPos[i + 4]); FFSWAP(int, filterPos[i + 3], filterPos[i + 5]); FFSWAP(int, filterPos[i + 10], filterPos[i + 12]); FFSWAP(int, filterPos[i + 11], filterPos[i + 13]); } if (filterSize > 4) { // 16 pixels are processed at a time. for (i = 0; i + 16 <= dstW; i += 16) { // 4 filter coeffs are processed at a time. for (k = 0; k + 4 <= filterSize; k += 4) { for (j = 0; j < 16; ++j) { int from = (i + j) * filterSize + k; int to = i * filterSize + j * 4 + k * 16; memcpy(&filter[to], &filterCopy[from], 4 * sizeof(int16_t)); } } } // 4 pixels are processed at a time in the tail. for (; i < dstW; i += 4) { // 4 filter coeffs are processed at a time. int rem = dstW - i >= 4 ? 4 : dstW - i; for (k = 0; k + 4 <= filterSize; k += 4) { for (j = 0; j < rem; ++j) { int from = (i + j) * filterSize + k; int to = i * filterSize + j * 4 + k * 4; memcpy(&filter[to], &filterCopy[from], 4 * sizeof(int16_t)); } } } } av_free(filterCopy); } } #endif return 0; } int sws_isSupportedInput(enum AVPixelFormat pix_fmt) { return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_in : 0; } int sws_isSupportedOutput(enum AVPixelFormat pix_fmt) { return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_out : 0; } int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt) { return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_endianness : 0; } static double getSplineCoeff(double a, double b, double c, double d, double dist) { if (dist <= 1.0) return ((d * dist + c) * dist + b) * dist + a; else return getSplineCoeff(0.0, b + 2.0 * c + 3.0 * d, c + 3.0 * d, -b - 3.0 * c - 6.0 * d, dist - 1.0); } static av_cold int get_local_pos(SwsInternal *s, int chr_subsample, int pos, int dir) { if (pos == -1 || pos <= -513) { pos = (128 << chr_subsample) - 128; } pos += 128; // relative to ideal left edge return pos >> chr_subsample; } typedef struct { int flag; ///< flag associated to the algorithm const char *description; ///< human-readable description int size_factor; ///< size factor used when initing the filters } ScaleAlgorithm; static const ScaleAlgorithm scale_algorithms[] = { { SWS_AREA, "area averaging", 1 /* downscale only, for upscale it is bilinear */ }, { SWS_BICUBIC, "bicubic", 4 }, { SWS_BICUBLIN, "luma bicubic / chroma bilinear", -1 }, { SWS_BILINEAR, "bilinear", 2 }, { SWS_FAST_BILINEAR, "fast bilinear", -1 }, { SWS_GAUSS, "Gaussian", 8 /* infinite ;) */ }, { SWS_LANCZOS, "Lanczos", -1 /* custom */ }, { SWS_POINT, "nearest neighbor / point", -1 }, { SWS_SINC, "sinc", 20 /* infinite ;) */ }, { SWS_SPLINE, "bicubic spline", 20 /* infinite :)*/ }, { SWS_X, "experimental", 8 }, }; static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, int *outFilterSize, int xInc, int srcW, int dstW, int filterAlign, int one, int flags, int cpu_flags, SwsVector *srcFilter, SwsVector *dstFilter, double param[2], int srcPos, int dstPos) { int i; int filterSize; int filter2Size; int minFilterSize; int64_t *filter = NULL; int64_t *filter2 = NULL; const int64_t fone = 1LL << (54 - FFMIN(av_log2(srcW/dstW), 8)); int ret = -1; emms_c(); // FIXME should not be required but IS (even for non-MMX versions) // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end if (!FF_ALLOC_TYPED_ARRAY(*filterPos, dstW + 3)) goto nomem; if (FFABS(xInc - 0x10000) < 10 && srcPos == dstPos) { // unscaled int i; filterSize = 1; if (!FF_ALLOCZ_TYPED_ARRAY(filter, dstW * filterSize)) goto nomem; for (i = 0; i < dstW; i++) { filter[i * filterSize] = fone; (*filterPos)[i] = i; } } else if (flags & SWS_POINT) { // lame looking point sampling mode int i; int64_t xDstInSrc; filterSize = 1; if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize)) goto nomem; xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); for (i = 0; i < dstW; i++) { int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16; (*filterPos)[i] = xx; filter[i] = fone; xDstInSrc += xInc; } } else if ((xInc <= (1 << 16) && (flags & SWS_AREA)) || (flags & SWS_FAST_BILINEAR)) { // bilinear upscale int i; int64_t xDstInSrc; filterSize = 2; if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize)) goto nomem; xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); for (i = 0; i < dstW; i++) { int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16; int j;