annotate ffmpeg/libswscale/utils.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
yading@11 3 *
yading@11 4 * This file is part of FFmpeg.
yading@11 5 *
yading@11 6 * FFmpeg is free software; you can redistribute it and/or
yading@11 7 * modify it under the terms of the GNU Lesser General Public
yading@11 8 * License as published by the Free Software Foundation; either
yading@11 9 * version 2.1 of the License, or (at your option) any later version.
yading@11 10 *
yading@11 11 * FFmpeg is distributed in the hope that it will be useful,
yading@11 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 14 * Lesser General Public License for more details.
yading@11 15 *
yading@11 16 * You should have received a copy of the GNU Lesser General Public
yading@11 17 * License along with FFmpeg; if not, write to the Free Software
yading@11 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 19 */
yading@11 20
yading@11 21 #include "config.h"
yading@11 22
yading@11 23 #define _SVID_SOURCE // needed for MAP_ANONYMOUS
yading@11 24 #define _DARWIN_C_SOURCE // needed for MAP_ANON
yading@11 25 #include <inttypes.h>
yading@11 26 #include <math.h>
yading@11 27 #include <stdio.h>
yading@11 28 #include <string.h>
yading@11 29 #if HAVE_SYS_MMAN_H
yading@11 30 #include <sys/mman.h>
yading@11 31 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
yading@11 32 #define MAP_ANONYMOUS MAP_ANON
yading@11 33 #endif
yading@11 34 #endif
yading@11 35 #if HAVE_VIRTUALALLOC
yading@11 36 #define WIN32_LEAN_AND_MEAN
yading@11 37 #include <windows.h>
yading@11 38 #endif
yading@11 39
yading@11 40 #include "libavutil/attributes.h"
yading@11 41 #include "libavutil/avassert.h"
yading@11 42 #include "libavutil/avutil.h"
yading@11 43 #include "libavutil/bswap.h"
yading@11 44 #include "libavutil/cpu.h"
yading@11 45 #include "libavutil/intreadwrite.h"
yading@11 46 #include "libavutil/mathematics.h"
yading@11 47 #include "libavutil/opt.h"
yading@11 48 #include "libavutil/pixdesc.h"
yading@11 49 #include "libavutil/x86/asm.h"
yading@11 50 #include "libavutil/x86/cpu.h"
yading@11 51 #include "rgb2rgb.h"
yading@11 52 #include "swscale.h"
yading@11 53 #include "swscale_internal.h"
yading@11 54
yading@11 55 unsigned swscale_version(void)
yading@11 56 {
yading@11 57 av_assert0(LIBSWSCALE_VERSION_MICRO >= 100);
yading@11 58 return LIBSWSCALE_VERSION_INT;
yading@11 59 }
yading@11 60
yading@11 61 const char *swscale_configuration(void)
yading@11 62 {
yading@11 63 return FFMPEG_CONFIGURATION;
yading@11 64 }
yading@11 65
yading@11 66 const char *swscale_license(void)
yading@11 67 {
yading@11 68 #define LICENSE_PREFIX "libswscale license: "
yading@11 69 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
yading@11 70 }
yading@11 71
yading@11 72 #define RET 0xC3 // near return opcode for x86
yading@11 73
yading@11 74 typedef struct FormatEntry {
yading@11 75 int is_supported_in, is_supported_out;
yading@11 76 } FormatEntry;
yading@11 77
yading@11 78 static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
yading@11 79 [AV_PIX_FMT_YUV420P] = { 1, 1 },
yading@11 80 [AV_PIX_FMT_YUYV422] = { 1, 1 },
yading@11 81 [AV_PIX_FMT_RGB24] = { 1, 1 },
yading@11 82 [AV_PIX_FMT_BGR24] = { 1, 1 },
yading@11 83 [AV_PIX_FMT_YUV422P] = { 1, 1 },
yading@11 84 [AV_PIX_FMT_YUV444P] = { 1, 1 },
yading@11 85 [AV_PIX_FMT_YUV410P] = { 1, 1 },
yading@11 86 [AV_PIX_FMT_YUV411P] = { 1, 1 },
yading@11 87 [AV_PIX_FMT_GRAY8] = { 1, 1 },
yading@11 88 [AV_PIX_FMT_MONOWHITE] = { 1, 1 },
yading@11 89 [AV_PIX_FMT_MONOBLACK] = { 1, 1 },
yading@11 90 [AV_PIX_FMT_PAL8] = { 1, 0 },
yading@11 91 [AV_PIX_FMT_YUVJ420P] = { 1, 1 },
yading@11 92 [AV_PIX_FMT_YUVJ422P] = { 1, 1 },
yading@11 93 [AV_PIX_FMT_YUVJ444P] = { 1, 1 },
yading@11 94 [AV_PIX_FMT_UYVY422] = { 1, 1 },
yading@11 95 [AV_PIX_FMT_UYYVYY411] = { 0, 0 },
yading@11 96 [AV_PIX_FMT_BGR8] = { 1, 1 },
yading@11 97 [AV_PIX_FMT_BGR4] = { 0, 1 },
yading@11 98 [AV_PIX_FMT_BGR4_BYTE] = { 1, 1 },
yading@11 99 [AV_PIX_FMT_RGB8] = { 1, 1 },
yading@11 100 [AV_PIX_FMT_RGB4] = { 0, 1 },
yading@11 101 [AV_PIX_FMT_RGB4_BYTE] = { 1, 1 },
yading@11 102 [AV_PIX_FMT_NV12] = { 1, 1 },
yading@11 103 [AV_PIX_FMT_NV21] = { 1, 1 },
yading@11 104 [AV_PIX_FMT_ARGB] = { 1, 1 },
yading@11 105 [AV_PIX_FMT_RGBA] = { 1, 1 },
yading@11 106 [AV_PIX_FMT_ABGR] = { 1, 1 },
yading@11 107 [AV_PIX_FMT_BGRA] = { 1, 1 },
yading@11 108 [AV_PIX_FMT_0RGB] = { 1, 1 },
yading@11 109 [AV_PIX_FMT_RGB0] = { 1, 1 },
yading@11 110 [AV_PIX_FMT_0BGR] = { 1, 1 },
yading@11 111 [AV_PIX_FMT_BGR0] = { 1, 1 },
yading@11 112 [AV_PIX_FMT_GRAY16BE] = { 1, 1 },
yading@11 113 [AV_PIX_FMT_GRAY16LE] = { 1, 1 },
yading@11 114 [AV_PIX_FMT_YUV440P] = { 1, 1 },
yading@11 115 [AV_PIX_FMT_YUVJ440P] = { 1, 1 },
yading@11 116 [AV_PIX_FMT_YUVA420P] = { 1, 1 },
yading@11 117 [AV_PIX_FMT_YUVA422P] = { 1, 1 },
yading@11 118 [AV_PIX_FMT_YUVA444P] = { 1, 1 },
yading@11 119 [AV_PIX_FMT_YUVA420P9BE] = { 1, 1 },
yading@11 120 [AV_PIX_FMT_YUVA420P9LE] = { 1, 1 },
yading@11 121 [AV_PIX_FMT_YUVA422P9BE] = { 1, 1 },
yading@11 122 [AV_PIX_FMT_YUVA422P9LE] = { 1, 1 },
yading@11 123 [AV_PIX_FMT_YUVA444P9BE] = { 1, 1 },
yading@11 124 [AV_PIX_FMT_YUVA444P9LE] = { 1, 1 },
yading@11 125 [AV_PIX_FMT_YUVA420P10BE]= { 1, 1 },
yading@11 126 [AV_PIX_FMT_YUVA420P10LE]= { 1, 1 },
yading@11 127 [AV_PIX_FMT_YUVA422P10BE]= { 1, 1 },
yading@11 128 [AV_PIX_FMT_YUVA422P10LE]= { 1, 1 },
yading@11 129 [AV_PIX_FMT_YUVA444P10BE]= { 1, 1 },
yading@11 130 [AV_PIX_FMT_YUVA444P10LE]= { 1, 1 },
yading@11 131 [AV_PIX_FMT_YUVA420P16BE]= { 1, 1 },
yading@11 132 [AV_PIX_FMT_YUVA420P16LE]= { 1, 1 },
yading@11 133 [AV_PIX_FMT_YUVA422P16BE]= { 1, 1 },
yading@11 134 [AV_PIX_FMT_YUVA422P16LE]= { 1, 1 },
yading@11 135 [AV_PIX_FMT_YUVA444P16BE]= { 1, 1 },
yading@11 136 [AV_PIX_FMT_YUVA444P16LE]= { 1, 1 },
yading@11 137 [AV_PIX_FMT_RGB48BE] = { 1, 1 },
yading@11 138 [AV_PIX_FMT_RGB48LE] = { 1, 1 },
yading@11 139 [AV_PIX_FMT_RGBA64BE] = { 1, 0 },
yading@11 140 [AV_PIX_FMT_RGBA64LE] = { 1, 0 },
yading@11 141 [AV_PIX_FMT_RGB565BE] = { 1, 1 },
yading@11 142 [AV_PIX_FMT_RGB565LE] = { 1, 1 },
yading@11 143 [AV_PIX_FMT_RGB555BE] = { 1, 1 },
yading@11 144 [AV_PIX_FMT_RGB555LE] = { 1, 1 },
yading@11 145 [AV_PIX_FMT_BGR565BE] = { 1, 1 },
yading@11 146 [AV_PIX_FMT_BGR565LE] = { 1, 1 },
yading@11 147 [AV_PIX_FMT_BGR555BE] = { 1, 1 },
yading@11 148 [AV_PIX_FMT_BGR555LE] = { 1, 1 },
yading@11 149 [AV_PIX_FMT_YUV420P16LE] = { 1, 1 },
yading@11 150 [AV_PIX_FMT_YUV420P16BE] = { 1, 1 },
yading@11 151 [AV_PIX_FMT_YUV422P16LE] = { 1, 1 },
yading@11 152 [AV_PIX_FMT_YUV422P16BE] = { 1, 1 },
yading@11 153 [AV_PIX_FMT_YUV444P16LE] = { 1, 1 },
yading@11 154 [AV_PIX_FMT_YUV444P16BE] = { 1, 1 },
yading@11 155 [AV_PIX_FMT_RGB444LE] = { 1, 1 },
yading@11 156 [AV_PIX_FMT_RGB444BE] = { 1, 1 },
yading@11 157 [AV_PIX_FMT_BGR444LE] = { 1, 1 },
yading@11 158 [AV_PIX_FMT_BGR444BE] = { 1, 1 },
yading@11 159 [AV_PIX_FMT_Y400A] = { 1, 0 },
yading@11 160 [AV_PIX_FMT_BGR48BE] = { 1, 1 },
yading@11 161 [AV_PIX_FMT_BGR48LE] = { 1, 1 },
yading@11 162 [AV_PIX_FMT_BGRA64BE] = { 0, 0 },
yading@11 163 [AV_PIX_FMT_BGRA64LE] = { 0, 0 },
yading@11 164 [AV_PIX_FMT_YUV420P9BE] = { 1, 1 },
yading@11 165 [AV_PIX_FMT_YUV420P9LE] = { 1, 1 },
yading@11 166 [AV_PIX_FMT_YUV420P10BE] = { 1, 1 },
yading@11 167 [AV_PIX_FMT_YUV420P10LE] = { 1, 1 },
yading@11 168 [AV_PIX_FMT_YUV420P12BE] = { 1, 1 },
yading@11 169 [AV_PIX_FMT_YUV420P12LE] = { 1, 1 },
yading@11 170 [AV_PIX_FMT_YUV420P14BE] = { 1, 1 },
yading@11 171 [AV_PIX_FMT_YUV420P14LE] = { 1, 1 },
yading@11 172 [AV_PIX_FMT_YUV422P9BE] = { 1, 1 },
yading@11 173 [AV_PIX_FMT_YUV422P9LE] = { 1, 1 },
yading@11 174 [AV_PIX_FMT_YUV422P10BE] = { 1, 1 },
yading@11 175 [AV_PIX_FMT_YUV422P10LE] = { 1, 1 },
yading@11 176 [AV_PIX_FMT_YUV422P12BE] = { 1, 1 },
yading@11 177 [AV_PIX_FMT_YUV422P12LE] = { 1, 1 },
yading@11 178 [AV_PIX_FMT_YUV422P14BE] = { 1, 1 },
yading@11 179 [AV_PIX_FMT_YUV422P14LE] = { 1, 1 },
yading@11 180 [AV_PIX_FMT_YUV444P9BE] = { 1, 1 },
yading@11 181 [AV_PIX_FMT_YUV444P9LE] = { 1, 1 },
yading@11 182 [AV_PIX_FMT_YUV444P10BE] = { 1, 1 },
yading@11 183 [AV_PIX_FMT_YUV444P10LE] = { 1, 1 },
yading@11 184 [AV_PIX_FMT_YUV444P12BE] = { 1, 1 },
yading@11 185 [AV_PIX_FMT_YUV444P12LE] = { 1, 1 },
yading@11 186 [AV_PIX_FMT_YUV444P14BE] = { 1, 1 },
yading@11 187 [AV_PIX_FMT_YUV444P14LE] = { 1, 1 },
yading@11 188 [AV_PIX_FMT_GBRP] = { 1, 1 },
yading@11 189 [AV_PIX_FMT_GBRP9LE] = { 1, 1 },
yading@11 190 [AV_PIX_FMT_GBRP9BE] = { 1, 1 },
yading@11 191 [AV_PIX_FMT_GBRP10LE] = { 1, 1 },
yading@11 192 [AV_PIX_FMT_GBRP10BE] = { 1, 1 },
yading@11 193 [AV_PIX_FMT_GBRP12LE] = { 1, 1 },
yading@11 194 [AV_PIX_FMT_GBRP12BE] = { 1, 1 },
yading@11 195 [AV_PIX_FMT_GBRP14LE] = { 1, 1 },
yading@11 196 [AV_PIX_FMT_GBRP14BE] = { 1, 1 },
yading@11 197 [AV_PIX_FMT_GBRP16LE] = { 1, 0 },
yading@11 198 [AV_PIX_FMT_GBRP16BE] = { 1, 0 },
yading@11 199 };
yading@11 200
yading@11 201 int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
yading@11 202 {
yading@11 203 return (unsigned)pix_fmt < AV_PIX_FMT_NB ?
yading@11 204 format_entries[pix_fmt].is_supported_in : 0;
yading@11 205 }
yading@11 206
yading@11 207 int sws_isSupportedOutput(enum AVPixelFormat pix_fmt)
yading@11 208 {
yading@11 209 return (unsigned)pix_fmt < AV_PIX_FMT_NB ?
yading@11 210 format_entries[pix_fmt].is_supported_out : 0;
yading@11 211 }
yading@11 212
yading@11 213 extern const int32_t ff_yuv2rgb_coeffs[8][4];
yading@11 214
yading@11 215 #if FF_API_SWS_FORMAT_NAME
yading@11 216 const char *sws_format_name(enum AVPixelFormat format)
yading@11 217 {
yading@11 218 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
yading@11 219 if (desc)
yading@11 220 return desc->name;
yading@11 221 else
yading@11 222 return "Unknown format";
yading@11 223 }
yading@11 224 #endif
yading@11 225
yading@11 226 static double getSplineCoeff(double a, double b, double c, double d,
yading@11 227 double dist)
yading@11 228 {
yading@11 229 if (dist <= 1.0)
yading@11 230 return ((d * dist + c) * dist + b) * dist + a;
yading@11 231 else
yading@11 232 return getSplineCoeff(0.0,
yading@11 233 b + 2.0 * c + 3.0 * d,
yading@11 234 c + 3.0 * d,
yading@11 235 -b - 3.0 * c - 6.0 * d,
yading@11 236 dist - 1.0);
yading@11 237 }
yading@11 238
yading@11 239 static int initFilter(int16_t **outFilter, int32_t **filterPos,
yading@11 240 int *outFilterSize, int xInc, int srcW, int dstW,
yading@11 241 int filterAlign, int one, int flags, int cpu_flags,
yading@11 242 SwsVector *srcFilter, SwsVector *dstFilter,
yading@11 243 double param[2])
yading@11 244 {
yading@11 245 int i;
yading@11 246 int filterSize;
yading@11 247 int filter2Size;
yading@11 248 int minFilterSize;
yading@11 249 int64_t *filter = NULL;
yading@11 250 int64_t *filter2 = NULL;
yading@11 251 const int64_t fone = 1LL << (54 - FFMIN(av_log2(srcW/dstW), 8));
yading@11 252 int ret = -1;
yading@11 253
yading@11 254 emms_c(); // FIXME should not be required but IS (even for non-MMX versions)
yading@11 255
yading@11 256 // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end
yading@11 257 FF_ALLOC_OR_GOTO(NULL, *filterPos, (dstW + 3) * sizeof(**filterPos), fail);
yading@11 258
yading@11 259 if (FFABS(xInc - 0x10000) < 10) { // unscaled
yading@11 260 int i;
yading@11 261 filterSize = 1;
yading@11 262 FF_ALLOCZ_OR_GOTO(NULL, filter,
yading@11 263 dstW * sizeof(*filter) * filterSize, fail);
yading@11 264
yading@11 265 for (i = 0; i < dstW; i++) {
yading@11 266 filter[i * filterSize] = fone;
yading@11 267 (*filterPos)[i] = i;
yading@11 268 }
yading@11 269 } else if (flags & SWS_POINT) { // lame looking point sampling mode
yading@11 270 int i;
yading@11 271 int64_t xDstInSrc;
yading@11 272 filterSize = 1;
yading@11 273 FF_ALLOC_OR_GOTO(NULL, filter,
yading@11 274 dstW * sizeof(*filter) * filterSize, fail);
yading@11 275
yading@11 276 xDstInSrc = xInc / 2 - 0x8000;
yading@11 277 for (i = 0; i < dstW; i++) {
yading@11 278 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
yading@11 279
yading@11 280 (*filterPos)[i] = xx;
yading@11 281 filter[i] = fone;
yading@11 282 xDstInSrc += xInc;
yading@11 283 }
yading@11 284 } else if ((xInc <= (1 << 16) && (flags & SWS_AREA)) ||
yading@11 285 (flags & SWS_FAST_BILINEAR)) { // bilinear upscale
yading@11 286 int i;
yading@11 287 int64_t xDstInSrc;
yading@11 288 filterSize = 2;
yading@11 289 FF_ALLOC_OR_GOTO(NULL, filter,
yading@11 290 dstW * sizeof(*filter) * filterSize, fail);
yading@11 291
yading@11 292 xDstInSrc = xInc / 2 - 0x8000;
yading@11 293 for (i = 0; i < dstW; i++) {
yading@11 294 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
yading@11 295 int j;
yading@11 296
yading@11 297 (*filterPos)[i] = xx;
yading@11 298 // bilinear upscale / linear interpolate / area averaging
yading@11 299 for (j = 0; j < filterSize; j++) {
yading@11 300 int64_t coeff= fone - FFABS(((int64_t)xx<<16) - xDstInSrc)*(fone>>16);
yading@11 301 if (coeff < 0)
yading@11 302 coeff = 0;
yading@11 303 filter[i * filterSize + j] = coeff;
yading@11 304 xx++;
yading@11 305 }
yading@11 306 xDstInSrc += xInc;
yading@11 307 }
yading@11 308 } else {
yading@11 309 int64_t xDstInSrc;
yading@11 310 int sizeFactor;
yading@11 311
yading@11 312 if (flags & SWS_BICUBIC)
yading@11 313 sizeFactor = 4;
yading@11 314 else if (flags & SWS_X)
yading@11 315 sizeFactor = 8;
yading@11 316 else if (flags & SWS_AREA)
yading@11 317 sizeFactor = 1; // downscale only, for upscale it is bilinear
yading@11 318 else if (flags & SWS_GAUSS)
yading@11 319 sizeFactor = 8; // infinite ;)
yading@11 320 else if (flags & SWS_LANCZOS)
yading@11 321 sizeFactor = param[0] != SWS_PARAM_DEFAULT ? ceil(2 * param[0]) : 6;
yading@11 322 else if (flags & SWS_SINC)
yading@11 323 sizeFactor = 20; // infinite ;)
yading@11 324 else if (flags & SWS_SPLINE)
yading@11 325 sizeFactor = 20; // infinite ;)
yading@11 326 else if (flags & SWS_BILINEAR)
yading@11 327 sizeFactor = 2;
yading@11 328 else {
yading@11 329 av_assert0(0);
yading@11 330 }
yading@11 331
yading@11 332 if (xInc <= 1 << 16)
yading@11 333 filterSize = 1 + sizeFactor; // upscale
yading@11 334 else
yading@11 335 filterSize = 1 + (sizeFactor * srcW + dstW - 1) / dstW;
yading@11 336
yading@11 337 filterSize = FFMIN(filterSize, srcW - 2);
yading@11 338 filterSize = FFMAX(filterSize, 1);
yading@11 339
yading@11 340 FF_ALLOC_OR_GOTO(NULL, filter,
yading@11 341 dstW * sizeof(*filter) * filterSize, fail);
yading@11 342
yading@11 343 xDstInSrc = xInc - 0x10000;
yading@11 344 for (i = 0; i < dstW; i++) {
yading@11 345 int xx = (xDstInSrc - ((filterSize - 2) << 16)) / (1 << 17);
yading@11 346 int j;
yading@11 347 (*filterPos)[i] = xx;
yading@11 348 for (j = 0; j < filterSize; j++) {
yading@11 349 int64_t d = (FFABS(((int64_t)xx << 17) - xDstInSrc)) << 13;
yading@11 350 double floatd;
yading@11 351 int64_t coeff;
yading@11 352
yading@11 353 if (xInc > 1 << 16)
yading@11 354 d = d * dstW / srcW;
yading@11 355 floatd = d * (1.0 / (1 << 30));
yading@11 356
yading@11 357 if (flags & SWS_BICUBIC) {
yading@11 358 int64_t B = (param[0] != SWS_PARAM_DEFAULT ? param[0] : 0) * (1 << 24);
yading@11 359 int64_t C = (param[1] != SWS_PARAM_DEFAULT ? param[1] : 0.6) * (1 << 24);
yading@11 360
yading@11 361 if (d >= 1LL << 31) {
yading@11 362 coeff = 0.0;
yading@11 363 } else {
yading@11 364 int64_t dd = (d * d) >> 30;
yading@11 365 int64_t ddd = (dd * d) >> 30;
yading@11 366
yading@11 367 if (d < 1LL << 30)
yading@11 368 coeff = (12 * (1 << 24) - 9 * B - 6 * C) * ddd +
yading@11 369 (-18 * (1 << 24) + 12 * B + 6 * C) * dd +
yading@11 370 (6 * (1 << 24) - 2 * B) * (1 << 30);
yading@11 371 else
yading@11 372 coeff = (-B - 6 * C) * ddd +
yading@11 373 (6 * B + 30 * C) * dd +
yading@11 374 (-12 * B - 48 * C) * d +
yading@11 375 (8 * B + 24 * C) * (1 << 30);
yading@11 376 }
yading@11 377 coeff /= (1LL<<54)/fone;
yading@11 378 }
yading@11 379 #if 0
yading@11 380 else if (flags & SWS_X) {
yading@11 381 double p = param ? param * 0.01 : 0.3;
yading@11 382 coeff = d ? sin(d * M_PI) / (d * M_PI) : 1.0;
yading@11 383 coeff *= pow(2.0, -p * d * d);
yading@11 384 }
yading@11 385 #endif
yading@11 386 else if (flags & SWS_X) {
yading@11 387 double A = param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0;
yading@11 388 double c;
yading@11 389
yading@11 390 if (floatd < 1.0)
yading@11 391 c = cos(floatd * M_PI);
yading@11 392 else
yading@11 393 c = -1.0;
yading@11 394 if (c < 0.0)
yading@11 395 c = -pow(-c, A);
yading@11 396 else
yading@11 397 c = pow(c, A);
yading@11 398 coeff = (c * 0.5 + 0.5) * fone;
yading@11 399 } else if (flags & SWS_AREA) {
yading@11 400 int64_t d2 = d - (1 << 29);
yading@11 401 if (d2 * xInc < -(1LL << (29 + 16)))
yading@11 402 coeff = 1.0 * (1LL << (30 + 16));
yading@11 403 else if (d2 * xInc < (1LL << (29 + 16)))
yading@11 404 coeff = -d2 * xInc + (1LL << (29 + 16));
yading@11 405 else
yading@11 406 coeff = 0.0;
yading@11 407 coeff *= fone >> (30 + 16);
yading@11 408 } else if (flags & SWS_GAUSS) {
yading@11 409 double p = param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
yading@11 410 coeff = (pow(2.0, -p * floatd * floatd)) * fone;
yading@11 411 } else if (flags & SWS_SINC) {
yading@11 412 coeff = (d ? sin(floatd * M_PI) / (floatd * M_PI) : 1.0) * fone;
yading@11 413 } else if (flags & SWS_LANCZOS) {
yading@11 414 double p = param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
yading@11 415 coeff = (d ? sin(floatd * M_PI) * sin(floatd * M_PI / p) /
yading@11 416 (floatd * floatd * M_PI * M_PI / p) : 1.0) * fone;
yading@11 417 if (floatd > p)
yading@11 418 coeff = 0;
yading@11 419 } else if (flags & SWS_BILINEAR) {
yading@11 420 coeff = (1 << 30) - d;
yading@11 421 if (coeff < 0)
yading@11 422 coeff = 0;
yading@11 423 coeff *= fone >> 30;
yading@11 424 } else if (flags & SWS_SPLINE) {
yading@11 425 double p = -2.196152422706632;
yading@11 426 coeff = getSplineCoeff(1.0, 0.0, p, -p - 1.0, floatd) * fone;
yading@11 427 } else {
yading@11 428 av_assert0(0);
yading@11 429 }
yading@11 430
yading@11 431 filter[i * filterSize + j] = coeff;
yading@11 432 xx++;
yading@11 433 }
yading@11 434 xDstInSrc += 2 * xInc;
yading@11 435 }
yading@11 436 }
yading@11 437
yading@11 438 /* apply src & dst Filter to filter -> filter2
yading@11 439 * av_free(filter);
yading@11 440 */
yading@11 441 av_assert0(filterSize > 0);
yading@11 442 filter2Size = filterSize;
yading@11 443 if (srcFilter)
yading@11 444 filter2Size += srcFilter->length - 1;
yading@11 445 if (dstFilter)
yading@11 446 filter2Size += dstFilter->length - 1;
yading@11 447 av_assert0(filter2Size > 0);
yading@11 448 FF_ALLOCZ_OR_GOTO(NULL, filter2, filter2Size * dstW * sizeof(*filter2), fail);
yading@11 449
yading@11 450 for (i = 0; i < dstW; i++) {
yading@11 451 int j, k;
yading@11 452
yading@11 453 if (srcFilter) {
yading@11 454 for (k = 0; k < srcFilter->length; k++) {
yading@11 455 for (j = 0; j < filterSize; j++)
yading@11 456 filter2[i * filter2Size + k + j] +=
yading@11 457 srcFilter->coeff[k] * filter[i * filterSize + j];
yading@11 458 }
yading@11 459 } else {
yading@11 460 for (j = 0; j < filterSize; j++)
yading@11 461 filter2[i * filter2Size + j] = filter[i * filterSize + j];
yading@11 462 }
yading@11 463 // FIXME dstFilter
yading@11 464
yading@11 465 (*filterPos)[i] += (filterSize - 1) / 2 - (filter2Size - 1) / 2;
yading@11 466 }
yading@11 467 av_freep(&filter);
yading@11 468
yading@11 469 /* try to reduce the filter-size (step1 find size and shift left) */
yading@11 470 // Assume it is near normalized (*0.5 or *2.0 is OK but * 0.001 is not).
yading@11 471 minFilterSize = 0;
yading@11 472 for (i = dstW - 1; i >= 0; i--) {
yading@11 473 int min = filter2Size;
yading@11 474 int j;
yading@11 475 int64_t cutOff = 0.0;
yading@11 476
yading@11 477 /* get rid of near zero elements on the left by shifting left */
yading@11 478 for (j = 0; j < filter2Size; j++) {
yading@11 479 int k;
yading@11 480 cutOff += FFABS(filter2[i * filter2Size]);
yading@11 481
yading@11 482 if (cutOff > SWS_MAX_REDUCE_CUTOFF * fone)
yading@11 483 break;
yading@11 484
yading@11 485 /* preserve monotonicity because the core can't handle the
yading@11 486 * filter otherwise */
yading@11 487 if (i < dstW - 1 && (*filterPos)[i] >= (*filterPos)[i + 1])
yading@11 488 break;
yading@11 489
yading@11 490 // move filter coefficients left
yading@11 491 for (k = 1; k < filter2Size; k++)
yading@11 492 filter2[i * filter2Size + k - 1] = filter2[i * filter2Size + k];
yading@11 493 filter2[i * filter2Size + k - 1] = 0;
yading@11 494 (*filterPos)[i]++;
yading@11 495 }
yading@11 496
yading@11 497 cutOff = 0;
yading@11 498 /* count near zeros on the right */
yading@11 499 for (j = filter2Size - 1; j > 0; j--) {
yading@11 500 cutOff += FFABS(filter2[i * filter2Size + j]);
yading@11 501
yading@11 502 if (cutOff > SWS_MAX_REDUCE_CUTOFF * fone)
yading@11 503 break;
yading@11 504 min--;
yading@11 505 }
yading@11 506
yading@11 507 if (min > minFilterSize)
yading@11 508 minFilterSize = min;
yading@11 509 }
yading@11 510
yading@11 511 if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) {
yading@11 512 // we can handle the special case 4, so we don't want to go the full 8
yading@11 513 if (minFilterSize < 5)
yading@11 514 filterAlign = 4;
yading@11 515
yading@11 516 /* We really don't want to waste our time doing useless computation, so
yading@11 517 * fall back on the scalar C code for very small filters.
yading@11 518 * Vectorizing is worth it only if you have a decent-sized vector. */
yading@11 519 if (minFilterSize < 3)
yading@11 520 filterAlign = 1;
yading@11 521 }
yading@11 522
yading@11 523 if (INLINE_MMX(cpu_flags)) {
yading@11 524 // special case for unscaled vertical filtering
yading@11 525 if (minFilterSize == 1 && filterAlign == 2)
yading@11 526 filterAlign = 1;
yading@11 527 }
yading@11 528
yading@11 529 av_assert0(minFilterSize > 0);
yading@11 530 filterSize = (minFilterSize + (filterAlign - 1)) & (~(filterAlign - 1));
yading@11 531 av_assert0(filterSize > 0);
yading@11 532 filter = av_malloc(filterSize * dstW * sizeof(*filter));
yading@11 533 if (filterSize >= MAX_FILTER_SIZE * 16 /
yading@11 534 ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16) || !filter) {
yading@11 535 av_log(NULL, AV_LOG_ERROR, "sws: filterSize %d is too large, try less extreem scaling or increase MAX_FILTER_SIZE and recompile\n", filterSize);
yading@11 536 goto fail;
yading@11 537 }
yading@11 538 *outFilterSize = filterSize;
yading@11 539
yading@11 540 if (flags & SWS_PRINT_INFO)
yading@11 541 av_log(NULL, AV_LOG_VERBOSE,
yading@11 542 "SwScaler: reducing / aligning filtersize %d -> %d\n",
yading@11 543 filter2Size, filterSize);
yading@11 544 /* try to reduce the filter-size (step2 reduce it) */
yading@11 545 for (i = 0; i < dstW; i++) {
yading@11 546 int j;
yading@11 547
yading@11 548 for (j = 0; j < filterSize; j++) {
yading@11 549 if (j >= filter2Size)
yading@11 550 filter[i * filterSize + j] = 0;
yading@11 551 else
yading@11 552 filter[i * filterSize + j] = filter2[i * filter2Size + j];
yading@11 553 if ((flags & SWS_BITEXACT) && j >= minFilterSize)
yading@11 554 filter[i * filterSize + j] = 0;
yading@11 555 }
yading@11 556 }
yading@11 557
yading@11 558 // FIXME try to align filterPos if possible
yading@11 559
yading@11 560 // fix borders
yading@11 561 for (i = 0; i < dstW; i++) {
yading@11 562 int j;
yading@11 563 if ((*filterPos)[i] < 0) {
yading@11 564 // move filter coefficients left to compensate for filterPos
yading@11 565 for (j = 1; j < filterSize; j++) {
yading@11 566 int left = FFMAX(j + (*filterPos)[i], 0);
yading@11 567 filter[i * filterSize + left] += filter[i * filterSize + j];
yading@11 568 filter[i * filterSize + j] = 0;
yading@11 569 }
yading@11 570 (*filterPos)[i]= 0;
yading@11 571 }
yading@11 572
yading@11 573 if ((*filterPos)[i] + filterSize > srcW) {
yading@11 574 int shift = (*filterPos)[i] + filterSize - srcW;
yading@11 575 // move filter coefficients right to compensate for filterPos
yading@11 576 for (j = filterSize - 2; j >= 0; j--) {
yading@11 577 int right = FFMIN(j + shift, filterSize - 1);
yading@11 578 filter[i * filterSize + right] += filter[i * filterSize + j];
yading@11 579 filter[i * filterSize + j] = 0;
yading@11 580 }
yading@11 581 (*filterPos)[i]= srcW - filterSize;
yading@11 582 }
yading@11 583 }
yading@11 584
yading@11 585 // Note the +1 is for the MMX scaler which reads over the end
yading@11 586 /* align at 16 for AltiVec (needed by hScale_altivec_real) */
yading@11 587 FF_ALLOCZ_OR_GOTO(NULL, *outFilter,
yading@11 588 *outFilterSize * (dstW + 3) * sizeof(int16_t), fail);
yading@11 589
yading@11 590 /* normalize & store in outFilter */
yading@11 591 for (i = 0; i < dstW; i++) {
yading@11 592 int j;
yading@11 593 int64_t error = 0;
yading@11 594 int64_t sum = 0;
yading@11 595
yading@11 596 for (j = 0; j < filterSize; j++) {
yading@11 597 sum += filter[i * filterSize + j];
yading@11 598 }
yading@11 599 sum = (sum + one / 2) / one;
yading@11 600 for (j = 0; j < *outFilterSize; j++) {
yading@11 601 int64_t v = filter[i * filterSize + j] + error;
yading@11 602 int intV = ROUNDED_DIV(v, sum);
yading@11 603 (*outFilter)[i * (*outFilterSize) + j] = intV;
yading@11 604 error = v - intV * sum;
yading@11 605 }
yading@11 606 }
yading@11 607
yading@11 608 (*filterPos)[dstW + 0] =
yading@11 609 (*filterPos)[dstW + 1] =
yading@11 610 (*filterPos)[dstW + 2] = (*filterPos)[dstW - 1]; /* the MMX/SSE scaler will
yading@11 611 * read over the end */
yading@11 612 for (i = 0; i < *outFilterSize; i++) {
yading@11 613 int k = (dstW - 1) * (*outFilterSize) + i;
yading@11 614 (*outFilter)[k + 1 * (*outFilterSize)] =
yading@11 615 (*outFilter)[k + 2 * (*outFilterSize)] =
yading@11 616 (*outFilter)[k + 3 * (*outFilterSize)] = (*outFilter)[k];
yading@11 617 }
yading@11 618
yading@11 619 ret = 0;
yading@11 620
yading@11 621 fail:
yading@11 622 if(ret < 0)
yading@11 623 av_log(NULL, AV_LOG_ERROR, "sws: initFilter failed\n");
yading@11 624 av_free(filter);
yading@11 625 av_free(filter2);
yading@11 626 return ret;
yading@11 627 }
yading@11 628
yading@11 629 #if HAVE_MMXEXT_INLINE
yading@11 630 static int init_hscaler_mmxext(int dstW, int xInc, uint8_t *filterCode,
yading@11 631 int16_t *filter, int32_t *filterPos,
yading@11 632 int numSplits)
yading@11 633 {
yading@11 634 uint8_t *fragmentA;
yading@11 635 x86_reg imm8OfPShufW1A;
yading@11 636 x86_reg imm8OfPShufW2A;
yading@11 637 x86_reg fragmentLengthA;
yading@11 638 uint8_t *fragmentB;
yading@11 639 x86_reg imm8OfPShufW1B;
yading@11 640 x86_reg imm8OfPShufW2B;
yading@11 641 x86_reg fragmentLengthB;
yading@11 642 int fragmentPos;
yading@11 643
yading@11 644 int xpos, i;
yading@11 645
yading@11 646 // create an optimized horizontal scaling routine
yading@11 647 /* This scaler is made of runtime-generated MMXEXT code using specially tuned
yading@11 648 * pshufw instructions. For every four output pixels, if four input pixels
yading@11 649 * are enough for the fast bilinear scaling, then a chunk of fragmentB is
yading@11 650 * used. If five input pixels are needed, then a chunk of fragmentA is used.
yading@11 651 */
yading@11 652
yading@11 653 // code fragment
yading@11 654
yading@11 655 __asm__ volatile (
yading@11 656 "jmp 9f \n\t"
yading@11 657 // Begin
yading@11 658 "0: \n\t"
yading@11 659 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t"
yading@11 660 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t"
yading@11 661 "movd 1(%%"REG_c", %%"REG_S"), %%mm1 \n\t"
yading@11 662 "punpcklbw %%mm7, %%mm1 \n\t"
yading@11 663 "punpcklbw %%mm7, %%mm0 \n\t"
yading@11 664 "pshufw $0xFF, %%mm1, %%mm1 \n\t"
yading@11 665 "1: \n\t"
yading@11 666 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
yading@11 667 "2: \n\t"
yading@11 668 "psubw %%mm1, %%mm0 \n\t"
yading@11 669 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t"
yading@11 670 "pmullw %%mm3, %%mm0 \n\t"
yading@11 671 "psllw $7, %%mm1 \n\t"
yading@11 672 "paddw %%mm1, %%mm0 \n\t"
yading@11 673
yading@11 674 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t"
yading@11 675
yading@11 676 "add $8, %%"REG_a" \n\t"
yading@11 677 // End
yading@11 678 "9: \n\t"
yading@11 679 // "int $3 \n\t"
yading@11 680 "lea " LOCAL_MANGLE(0b) ", %0 \n\t"
yading@11 681 "lea " LOCAL_MANGLE(1b) ", %1 \n\t"
yading@11 682 "lea " LOCAL_MANGLE(2b) ", %2 \n\t"
yading@11 683 "dec %1 \n\t"
yading@11 684 "dec %2 \n\t"
yading@11 685 "sub %0, %1 \n\t"
yading@11 686 "sub %0, %2 \n\t"
yading@11 687 "lea " LOCAL_MANGLE(9b) ", %3 \n\t"
yading@11 688 "sub %0, %3 \n\t"
yading@11 689
yading@11 690
yading@11 691 : "=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A),
yading@11 692 "=r" (fragmentLengthA)
yading@11 693 );
yading@11 694
yading@11 695 __asm__ volatile (
yading@11 696 "jmp 9f \n\t"
yading@11 697 // Begin
yading@11 698 "0: \n\t"
yading@11 699 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t"
yading@11 700 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t"
yading@11 701 "punpcklbw %%mm7, %%mm0 \n\t"
yading@11 702 "pshufw $0xFF, %%mm0, %%mm1 \n\t"
yading@11 703 "1: \n\t"
yading@11 704 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
yading@11 705 "2: \n\t"
yading@11 706 "psubw %%mm1, %%mm0 \n\t"
yading@11 707 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t"
yading@11 708 "pmullw %%mm3, %%mm0 \n\t"
yading@11 709 "psllw $7, %%mm1 \n\t"
yading@11 710 "paddw %%mm1, %%mm0 \n\t"
yading@11 711
yading@11 712 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t"
yading@11 713
yading@11 714 "add $8, %%"REG_a" \n\t"
yading@11 715 // End
yading@11 716 "9: \n\t"
yading@11 717 // "int $3 \n\t"
yading@11 718 "lea " LOCAL_MANGLE(0b) ", %0 \n\t"
yading@11 719 "lea " LOCAL_MANGLE(1b) ", %1 \n\t"
yading@11 720 "lea " LOCAL_MANGLE(2b) ", %2 \n\t"
yading@11 721 "dec %1 \n\t"
yading@11 722 "dec %2 \n\t"
yading@11 723 "sub %0, %1 \n\t"
yading@11 724 "sub %0, %2 \n\t"
yading@11 725 "lea " LOCAL_MANGLE(9b) ", %3 \n\t"
yading@11 726 "sub %0, %3 \n\t"
yading@11 727
yading@11 728
yading@11 729 : "=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B),
yading@11 730 "=r" (fragmentLengthB)
yading@11 731 );
yading@11 732
yading@11 733 xpos = 0; // lumXInc/2 - 0x8000; // difference between pixel centers
yading@11 734 fragmentPos = 0;
yading@11 735
yading@11 736 for (i = 0; i < dstW / numSplits; i++) {
yading@11 737 int xx = xpos >> 16;
yading@11 738
yading@11 739 if ((i & 3) == 0) {
yading@11 740 int a = 0;
yading@11 741 int b = ((xpos + xInc) >> 16) - xx;
yading@11 742 int c = ((xpos + xInc * 2) >> 16) - xx;
yading@11 743 int d = ((xpos + xInc * 3) >> 16) - xx;
yading@11 744 int inc = (d + 1 < 4);
yading@11 745 uint8_t *fragment = (d + 1 < 4) ? fragmentB : fragmentA;
yading@11 746 x86_reg imm8OfPShufW1 = (d + 1 < 4) ? imm8OfPShufW1B : imm8OfPShufW1A;
yading@11 747 x86_reg imm8OfPShufW2 = (d + 1 < 4) ? imm8OfPShufW2B : imm8OfPShufW2A;
yading@11 748 x86_reg fragmentLength = (d + 1 < 4) ? fragmentLengthB : fragmentLengthA;
yading@11 749 int maxShift = 3 - (d + inc);
yading@11 750 int shift = 0;
yading@11 751
yading@11 752 if (filterCode) {
yading@11 753 filter[i] = ((xpos & 0xFFFF) ^ 0xFFFF) >> 9;
yading@11 754 filter[i + 1] = (((xpos + xInc) & 0xFFFF) ^ 0xFFFF) >> 9;
yading@11 755 filter[i + 2] = (((xpos + xInc * 2) & 0xFFFF) ^ 0xFFFF) >> 9;
yading@11 756 filter[i + 3] = (((xpos + xInc * 3) & 0xFFFF) ^ 0xFFFF) >> 9;
yading@11 757 filterPos[i / 2] = xx;
yading@11 758
yading@11 759 memcpy(filterCode + fragmentPos, fragment, fragmentLength);
yading@11 760
yading@11 761 filterCode[fragmentPos + imm8OfPShufW1] = (a + inc) |
yading@11 762 ((b + inc) << 2) |
yading@11 763 ((c + inc) << 4) |
yading@11 764 ((d + inc) << 6);
yading@11 765 filterCode[fragmentPos + imm8OfPShufW2] = a | (b << 2) |
yading@11 766 (c << 4) |
yading@11 767 (d << 6);
yading@11 768
yading@11 769 if (i + 4 - inc >= dstW)
yading@11 770 shift = maxShift; // avoid overread
yading@11 771 else if ((filterPos[i / 2] & 3) <= maxShift)
yading@11 772 shift = filterPos[i / 2] & 3; // align
yading@11 773
yading@11 774 if (shift && i >= shift) {
yading@11 775 filterCode[fragmentPos + imm8OfPShufW1] += 0x55 * shift;
yading@11 776 filterCode[fragmentPos + imm8OfPShufW2] += 0x55 * shift;
yading@11 777 filterPos[i / 2] -= shift;
yading@11 778 }
yading@11 779 }
yading@11 780
yading@11 781 fragmentPos += fragmentLength;
yading@11 782
yading@11 783 if (filterCode)
yading@11 784 filterCode[fragmentPos] = RET;
yading@11 785 }
yading@11 786 xpos += xInc;
yading@11 787 }
yading@11 788 if (filterCode)
yading@11 789 filterPos[((i / 2) + 1) & (~1)] = xpos >> 16; // needed to jump to the next part
yading@11 790
yading@11 791 return fragmentPos + 1;
yading@11 792 }
yading@11 793 #endif /* HAVE_MMXEXT_INLINE */
yading@11 794
yading@11 795 static void getSubSampleFactors(int *h, int *v, enum AVPixelFormat format)
yading@11 796 {
yading@11 797 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
yading@11 798 *h = desc->log2_chroma_w;
yading@11 799 *v = desc->log2_chroma_h;
yading@11 800 }
yading@11 801
yading@11 802 static void fill_rgb2yuv_table(SwsContext *c, const int table[4], int dstRange)
yading@11 803 {
yading@11 804 int64_t W, V, Z, Cy, Cu, Cv;
yading@11 805 int64_t vr = table[0];
yading@11 806 int64_t ub = table[1];
yading@11 807 int64_t ug = -table[2];
yading@11 808 int64_t vg = -table[3];
yading@11 809 int64_t ONE = 65536;
yading@11 810 int64_t cy = ONE;
yading@11 811 uint8_t *p = (uint8_t*)c->input_rgb2yuv_table;
yading@11 812 int i;
yading@11 813 static const int8_t map[] = {
yading@11 814 BY_IDX, GY_IDX, -1 , BY_IDX, BY_IDX, GY_IDX, -1 , BY_IDX,
yading@11 815 RY_IDX, -1 , GY_IDX, RY_IDX, RY_IDX, -1 , GY_IDX, RY_IDX,
yading@11 816 RY_IDX, GY_IDX, -1 , RY_IDX, RY_IDX, GY_IDX, -1 , RY_IDX,
yading@11 817 BY_IDX, -1 , GY_IDX, BY_IDX, BY_IDX, -1 , GY_IDX, BY_IDX,
yading@11 818 BU_IDX, GU_IDX, -1 , BU_IDX, BU_IDX, GU_IDX, -1 , BU_IDX,
yading@11 819 RU_IDX, -1 , GU_IDX, RU_IDX, RU_IDX, -1 , GU_IDX, RU_IDX,
yading@11 820 RU_IDX, GU_IDX, -1 , RU_IDX, RU_IDX, GU_IDX, -1 , RU_IDX,
yading@11 821 BU_IDX, -1 , GU_IDX, BU_IDX, BU_IDX, -1 , GU_IDX, BU_IDX,
yading@11 822 BV_IDX, GV_IDX, -1 , BV_IDX, BV_IDX, GV_IDX, -1 , BV_IDX,
yading@11 823 RV_IDX, -1 , GV_IDX, RV_IDX, RV_IDX, -1 , GV_IDX, RV_IDX,
yading@11 824 RV_IDX, GV_IDX, -1 , RV_IDX, RV_IDX, GV_IDX, -1 , RV_IDX,
yading@11 825 BV_IDX, -1 , GV_IDX, BV_IDX, BV_IDX, -1 , GV_IDX, BV_IDX,
yading@11 826 RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX,
yading@11 827 BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX,
yading@11 828 GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 ,
yading@11 829 -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX,
yading@11 830 RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX,
yading@11 831 BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX,
yading@11 832 GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 ,
yading@11 833 -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX,
yading@11 834 RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX,
yading@11 835 BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX,
yading@11 836 GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 ,
yading@11 837 -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, //23
yading@11 838 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //24
yading@11 839 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //25
yading@11 840 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //26
yading@11 841 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //27
yading@11 842 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //28
yading@11 843 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //29
yading@11 844 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //30
yading@11 845 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //31
yading@11 846 BY_IDX, GY_IDX, RY_IDX, -1 , -1 , -1 , -1 , -1 , //32
yading@11 847 BU_IDX, GU_IDX, RU_IDX, -1 , -1 , -1 , -1 , -1 , //33
yading@11 848 BV_IDX, GV_IDX, RV_IDX, -1 , -1 , -1 , -1 , -1 , //34
yading@11 849 };
yading@11 850
yading@11 851 dstRange = 0; //FIXME range = 1 is handled elsewhere
yading@11 852
yading@11 853 if (!dstRange) {
yading@11 854 cy = cy * 255 / 219;
yading@11 855 } else {
yading@11 856 vr = vr * 224 / 255;
yading@11 857 ub = ub * 224 / 255;
yading@11 858 ug = ug * 224 / 255;
yading@11 859 vg = vg * 224 / 255;
yading@11 860 }
yading@11 861 W = ROUNDED_DIV(ONE*ONE*ug, ub);
yading@11 862 V = ROUNDED_DIV(ONE*ONE*vg, vr);
yading@11 863 Z = ONE*ONE-W-V;
yading@11 864
yading@11 865 Cy = ROUNDED_DIV(cy*Z, ONE);
yading@11 866 Cu = ROUNDED_DIV(ub*Z, ONE);
yading@11 867 Cv = ROUNDED_DIV(vr*Z, ONE);
yading@11 868
yading@11 869 c->input_rgb2yuv_table[RY_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*V , Cy);
yading@11 870 c->input_rgb2yuv_table[GY_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cy);
yading@11 871 c->input_rgb2yuv_table[BY_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*W , Cy);
yading@11 872
yading@11 873 c->input_rgb2yuv_table[RU_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*V , Cu);
yading@11 874 c->input_rgb2yuv_table[GU_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cu);
yading@11 875 c->input_rgb2yuv_table[BU_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*(Z+W) , Cu);
yading@11 876
yading@11 877 c->input_rgb2yuv_table[RV_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*(V+Z) , Cv);
yading@11 878 c->input_rgb2yuv_table[GV_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cv);
yading@11 879 c->input_rgb2yuv_table[BV_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*W , Cv);
yading@11 880
yading@11 881 if(/*!dstRange && */table == ff_yuv2rgb_coeffs[SWS_CS_DEFAULT]) {
yading@11 882 c->input_rgb2yuv_table[BY_IDX] = ((int)(0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 883 c->input_rgb2yuv_table[BV_IDX] = (-(int)(0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 884 c->input_rgb2yuv_table[BU_IDX] = ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 885 c->input_rgb2yuv_table[GY_IDX] = ((int)(0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 886 c->input_rgb2yuv_table[GV_IDX] = (-(int)(0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 887 c->input_rgb2yuv_table[GU_IDX] = (-(int)(0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 888 c->input_rgb2yuv_table[RY_IDX] = ((int)(0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 889 c->input_rgb2yuv_table[RV_IDX] = ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 890 c->input_rgb2yuv_table[RU_IDX] = (-(int)(0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
yading@11 891 }
yading@11 892 for(i=0; i<FF_ARRAY_ELEMS(map); i++)
yading@11 893 AV_WL16(p + 16*4 + 2*i, map[i] >= 0 ? c->input_rgb2yuv_table[map[i]] : 0);
yading@11 894 }
yading@11 895
yading@11 896 int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
yading@11 897 int srcRange, const int table[4], int dstRange,
yading@11 898 int brightness, int contrast, int saturation)
yading@11 899 {
yading@11 900 const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
yading@11 901 const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
yading@11 902 memcpy(c->srcColorspaceTable, inv_table, sizeof(int) * 4);
yading@11 903 memcpy(c->dstColorspaceTable, table, sizeof(int) * 4);
yading@11 904
yading@11 905 if(!isYUV(c->dstFormat) && !isGray(c->dstFormat))
yading@11 906 dstRange = 0;
yading@11 907 if(!isYUV(c->srcFormat) && !isGray(c->srcFormat))
yading@11 908 srcRange = 0;
yading@11 909
yading@11 910 c->brightness = brightness;
yading@11 911 c->contrast = contrast;
yading@11 912 c->saturation = saturation;
yading@11 913 c->srcRange = srcRange;
yading@11 914 c->dstRange = dstRange;
yading@11 915
yading@11 916 if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat)))
yading@11 917 return -1;
yading@11 918
yading@11 919 c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
yading@11 920 c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
yading@11 921
yading@11 922 if (!isYUV(c->dstFormat) && !isGray(c->dstFormat)) {
yading@11 923 ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness,
yading@11 924 contrast, saturation);
yading@11 925 // FIXME factorize
yading@11 926
yading@11 927 if (HAVE_ALTIVEC && av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)
yading@11 928 ff_yuv2rgb_init_tables_altivec(c, inv_table, brightness,
yading@11 929 contrast, saturation);
yading@11 930 }
yading@11 931
yading@11 932 fill_rgb2yuv_table(c, table, dstRange);
yading@11 933
yading@11 934 return 0;
yading@11 935 }
yading@11 936
yading@11 937 int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
yading@11 938 int *srcRange, int **table, int *dstRange,
yading@11 939 int *brightness, int *contrast, int *saturation)
yading@11 940 {
yading@11 941 if (!c || isYUV(c->dstFormat) || isGray(c->dstFormat))
yading@11 942 return -1;
yading@11 943
yading@11 944 *inv_table = c->srcColorspaceTable;
yading@11 945 *table = c->dstColorspaceTable;
yading@11 946 *srcRange = c->srcRange;
yading@11 947 *dstRange = c->dstRange;
yading@11 948 *brightness = c->brightness;
yading@11 949 *contrast = c->contrast;
yading@11 950 *saturation = c->saturation;
yading@11 951
yading@11 952 return 0;
yading@11 953 }
yading@11 954
yading@11 955 static int handle_jpeg(enum AVPixelFormat *format)
yading@11 956 {
yading@11 957 switch (*format) {
yading@11 958 case AV_PIX_FMT_YUVJ420P:
yading@11 959 *format = AV_PIX_FMT_YUV420P;
yading@11 960 return 1;
yading@11 961 case AV_PIX_FMT_YUVJ422P:
yading@11 962 *format = AV_PIX_FMT_YUV422P;
yading@11 963 return 1;
yading@11 964 case AV_PIX_FMT_YUVJ444P:
yading@11 965 *format = AV_PIX_FMT_YUV444P;
yading@11 966 return 1;
yading@11 967 case AV_PIX_FMT_YUVJ440P:
yading@11 968 *format = AV_PIX_FMT_YUV440P;
yading@11 969 return 1;
yading@11 970 default:
yading@11 971 return 0;
yading@11 972 }
yading@11 973 }
yading@11 974
yading@11 975 static int handle_0alpha(enum AVPixelFormat *format)
yading@11 976 {
yading@11 977 switch (*format) {
yading@11 978 case AV_PIX_FMT_0BGR : *format = AV_PIX_FMT_ABGR ; return 1;
yading@11 979 case AV_PIX_FMT_BGR0 : *format = AV_PIX_FMT_BGRA ; return 4;
yading@11 980 case AV_PIX_FMT_0RGB : *format = AV_PIX_FMT_ARGB ; return 1;
yading@11 981 case AV_PIX_FMT_RGB0 : *format = AV_PIX_FMT_RGBA ; return 4;
yading@11 982 default: return 0;
yading@11 983 }
yading@11 984 }
yading@11 985
yading@11 986 SwsContext *sws_alloc_context(void)
yading@11 987 {
yading@11 988 SwsContext *c = av_mallocz(sizeof(SwsContext));
yading@11 989
yading@11 990 if (c) {
yading@11 991 c->av_class = &sws_context_class;
yading@11 992 av_opt_set_defaults(c);
yading@11 993 }
yading@11 994
yading@11 995 return c;
yading@11 996 }
yading@11 997
yading@11 998 av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
yading@11 999 SwsFilter *dstFilter)
yading@11 1000 {
yading@11 1001 int i, j;
yading@11 1002 int usesVFilter, usesHFilter;
yading@11 1003 int unscaled;
yading@11 1004 SwsFilter dummyFilter = { NULL, NULL, NULL, NULL };
yading@11 1005 int srcW = c->srcW;
yading@11 1006 int srcH = c->srcH;
yading@11 1007 int dstW = c->dstW;
yading@11 1008 int dstH = c->dstH;
yading@11 1009 int dst_stride = FFALIGN(dstW * sizeof(int16_t) + 66, 16);
yading@11 1010 int flags, cpu_flags;
yading@11 1011 enum AVPixelFormat srcFormat = c->srcFormat;
yading@11 1012 enum AVPixelFormat dstFormat = c->dstFormat;
yading@11 1013 const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(srcFormat);
yading@11 1014 const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat);
yading@11 1015
yading@11 1016 cpu_flags = av_get_cpu_flags();
yading@11 1017 flags = c->flags;
yading@11 1018 emms_c();
yading@11 1019 if (!rgb15to16)
yading@11 1020 sws_rgb2rgb_init();
yading@11 1021
yading@11 1022 unscaled = (srcW == dstW && srcH == dstH);
yading@11 1023
yading@11 1024 handle_jpeg(&srcFormat);
yading@11 1025 handle_jpeg(&dstFormat);
yading@11 1026 handle_0alpha(&srcFormat);
yading@11 1027 handle_0alpha(&dstFormat);
yading@11 1028
yading@11 1029 if(srcFormat!=c->srcFormat || dstFormat!=c->dstFormat){
yading@11 1030 av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
yading@11 1031 c->srcFormat= srcFormat;
yading@11 1032 c->dstFormat= dstFormat;
yading@11 1033 }
yading@11 1034
yading@11 1035 if (!sws_isSupportedInput(srcFormat)) {
yading@11 1036 av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n",
yading@11 1037 av_get_pix_fmt_name(srcFormat));
yading@11 1038 return AVERROR(EINVAL);
yading@11 1039 }
yading@11 1040 if (!sws_isSupportedOutput(dstFormat)) {
yading@11 1041 av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n",
yading@11 1042 av_get_pix_fmt_name(dstFormat));
yading@11 1043 return AVERROR(EINVAL);
yading@11 1044 }
yading@11 1045
yading@11 1046 i = flags & (SWS_POINT |
yading@11 1047 SWS_AREA |
yading@11 1048 SWS_BILINEAR |
yading@11 1049 SWS_FAST_BILINEAR |
yading@11 1050 SWS_BICUBIC |
yading@11 1051 SWS_X |
yading@11 1052 SWS_GAUSS |
yading@11 1053 SWS_LANCZOS |
yading@11 1054 SWS_SINC |
yading@11 1055 SWS_SPLINE |
yading@11 1056 SWS_BICUBLIN);
yading@11 1057 if (!i || (i & (i - 1))) {
yading@11 1058 av_log(c, AV_LOG_ERROR, "Exactly one scaler algorithm must be chosen, got %X\n", i);
yading@11 1059 return AVERROR(EINVAL);
yading@11 1060 }
yading@11 1061 /* sanity check */
yading@11 1062 if (srcW < 1 || srcH < 1 || dstW < 1 || dstH < 1) {
yading@11 1063 /* FIXME check if these are enough and try to lower them after
yading@11 1064 * fixing the relevant parts of the code */
yading@11 1065 av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",
yading@11 1066 srcW, srcH, dstW, dstH);
yading@11 1067 return AVERROR(EINVAL);
yading@11 1068 }
yading@11 1069
yading@11 1070 if (!dstFilter)
yading@11 1071 dstFilter = &dummyFilter;
yading@11 1072 if (!srcFilter)
yading@11 1073 srcFilter = &dummyFilter;
yading@11 1074
yading@11 1075 c->lumXInc = (((int64_t)srcW << 16) + (dstW >> 1)) / dstW;
yading@11 1076 c->lumYInc = (((int64_t)srcH << 16) + (dstH >> 1)) / dstH;
yading@11 1077 c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
yading@11 1078 c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
yading@11 1079 c->vRounder = 4 * 0x0001000100010001ULL;
yading@11 1080
yading@11 1081 usesVFilter = (srcFilter->lumV && srcFilter->lumV->length > 1) ||
yading@11 1082 (srcFilter->chrV && srcFilter->chrV->length > 1) ||
yading@11 1083 (dstFilter->lumV && dstFilter->lumV->length > 1) ||
yading@11 1084 (dstFilter->chrV && dstFilter->chrV->length > 1);
yading@11 1085 usesHFilter = (srcFilter->lumH && srcFilter->lumH->length > 1) ||
yading@11 1086 (srcFilter->chrH && srcFilter->chrH->length > 1) ||
yading@11 1087 (dstFilter->lumH && dstFilter->lumH->length > 1) ||
yading@11 1088 (dstFilter->chrH && dstFilter->chrH->length > 1);
yading@11 1089
yading@11 1090 getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
yading@11 1091 getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
yading@11 1092
yading@11 1093 if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) {
yading@11 1094 if (dstW&1) {
yading@11 1095 av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n");
yading@11 1096 flags |= SWS_FULL_CHR_H_INT;
yading@11 1097 c->flags = flags;
yading@11 1098 }
yading@11 1099 }
yading@11 1100
yading@11 1101 if(dstFormat == AV_PIX_FMT_BGR4_BYTE ||
yading@11 1102 dstFormat == AV_PIX_FMT_RGB4_BYTE ||
yading@11 1103 dstFormat == AV_PIX_FMT_BGR8 ||
yading@11 1104 dstFormat == AV_PIX_FMT_RGB8) {
yading@11 1105 if (flags & SWS_ERROR_DIFFUSION && !(flags & SWS_FULL_CHR_H_INT)) {
yading@11 1106 av_log(c, AV_LOG_DEBUG,
yading@11 1107 "Error diffusion dither is only supported in full chroma interpolation for destination format '%s'\n",
yading@11 1108 av_get_pix_fmt_name(dstFormat));
yading@11 1109 flags |= SWS_FULL_CHR_H_INT;
yading@11 1110 c->flags = flags;
yading@11 1111 }
yading@11 1112 if (!(flags & SWS_ERROR_DIFFUSION) && (flags & SWS_FULL_CHR_H_INT)) {
yading@11 1113 av_log(c, AV_LOG_DEBUG,
yading@11 1114 "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
yading@11 1115 av_get_pix_fmt_name(dstFormat));
yading@11 1116 flags |= SWS_ERROR_DIFFUSION;
yading@11 1117 c->flags = flags;
yading@11 1118 }
yading@11 1119 }
yading@11 1120 if (isPlanarRGB(dstFormat)) {
yading@11 1121 if (!(flags & SWS_FULL_CHR_H_INT)) {
yading@11 1122 av_log(c, AV_LOG_DEBUG,
yading@11 1123 "%s output is not supported with half chroma resolution, switching to full\n",
yading@11 1124 av_get_pix_fmt_name(dstFormat));
yading@11 1125 flags |= SWS_FULL_CHR_H_INT;
yading@11 1126 c->flags = flags;
yading@11 1127 }
yading@11 1128 }
yading@11 1129
yading@11 1130 /* reuse chroma for 2 pixels RGB/BGR unless user wants full
yading@11 1131 * chroma interpolation */
yading@11 1132 if (flags & SWS_FULL_CHR_H_INT &&
yading@11 1133 isAnyRGB(dstFormat) &&
yading@11 1134 !isPlanarRGB(dstFormat) &&
yading@11 1135 dstFormat != AV_PIX_FMT_RGBA &&
yading@11 1136 dstFormat != AV_PIX_FMT_ARGB &&
yading@11 1137 dstFormat != AV_PIX_FMT_BGRA &&
yading@11 1138 dstFormat != AV_PIX_FMT_ABGR &&
yading@11 1139 dstFormat != AV_PIX_FMT_RGB24 &&
yading@11 1140 dstFormat != AV_PIX_FMT_BGR24 &&
yading@11 1141 dstFormat != AV_PIX_FMT_BGR4_BYTE &&
yading@11 1142 dstFormat != AV_PIX_FMT_RGB4_BYTE &&
yading@11 1143 dstFormat != AV_PIX_FMT_BGR8 &&
yading@11 1144 dstFormat != AV_PIX_FMT_RGB8
yading@11 1145 ) {
yading@11 1146 av_log(c, AV_LOG_WARNING,
yading@11 1147 "full chroma interpolation for destination format '%s' not yet implemented\n",
yading@11 1148 av_get_pix_fmt_name(dstFormat));
yading@11 1149 flags &= ~SWS_FULL_CHR_H_INT;
yading@11 1150 c->flags = flags;
yading@11 1151 }
yading@11 1152 if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))
yading@11 1153 c->chrDstHSubSample = 1;
yading@11 1154
yading@11 1155 // drop some chroma lines if the user wants it
yading@11 1156 c->vChrDrop = (flags & SWS_SRC_V_CHR_DROP_MASK) >>
yading@11 1157 SWS_SRC_V_CHR_DROP_SHIFT;
yading@11 1158 c->chrSrcVSubSample += c->vChrDrop;
yading@11 1159
yading@11 1160 /* drop every other pixel for chroma calculation unless user
yading@11 1161 * wants full chroma */
yading@11 1162 if (isAnyRGB(srcFormat) && !(flags & SWS_FULL_CHR_H_INP) &&
yading@11 1163 srcFormat != AV_PIX_FMT_RGB8 && srcFormat != AV_PIX_FMT_BGR8 &&
yading@11 1164 srcFormat != AV_PIX_FMT_RGB4 && srcFormat != AV_PIX_FMT_BGR4 &&
yading@11 1165 srcFormat != AV_PIX_FMT_RGB4_BYTE && srcFormat != AV_PIX_FMT_BGR4_BYTE &&
yading@11 1166 srcFormat != AV_PIX_FMT_GBRP9BE && srcFormat != AV_PIX_FMT_GBRP9LE &&
yading@11 1167 srcFormat != AV_PIX_FMT_GBRP10BE && srcFormat != AV_PIX_FMT_GBRP10LE &&
yading@11 1168 srcFormat != AV_PIX_FMT_GBRP12BE && srcFormat != AV_PIX_FMT_GBRP12LE &&
yading@11 1169 srcFormat != AV_PIX_FMT_GBRP14BE && srcFormat != AV_PIX_FMT_GBRP14LE &&
yading@11 1170 srcFormat != AV_PIX_FMT_GBRP16BE && srcFormat != AV_PIX_FMT_GBRP16LE &&
yading@11 1171 ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) ||
yading@11 1172 (flags & SWS_FAST_BILINEAR)))
yading@11 1173 c->chrSrcHSubSample = 1;
yading@11 1174
yading@11 1175 // Note the -((-x)>>y) is so that we always round toward +inf.
yading@11 1176 c->chrSrcW = -((-srcW) >> c->chrSrcHSubSample);
yading@11 1177 c->chrSrcH = -((-srcH) >> c->chrSrcVSubSample);
yading@11 1178 c->chrDstW = -((-dstW) >> c->chrDstHSubSample);
yading@11 1179 c->chrDstH = -((-dstH) >> c->chrDstVSubSample);
yading@11 1180
yading@11 1181 FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW*2+78, 16) * 2, fail);
yading@11 1182
yading@11 1183 /* unscaled special cases */
yading@11 1184 if (unscaled && !usesHFilter && !usesVFilter &&
yading@11 1185 (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) {
yading@11 1186 ff_get_unscaled_swscale(c);
yading@11 1187
yading@11 1188 if (c->swScale) {
yading@11 1189 if (flags & SWS_PRINT_INFO)
yading@11 1190 av_log(c, AV_LOG_INFO,
yading@11 1191 "using unscaled %s -> %s special converter\n",
yading@11 1192 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
yading@11 1193 return 0;
yading@11 1194 }
yading@11 1195 }
yading@11 1196
yading@11 1197 c->srcBpc = 1 + desc_src->comp[0].depth_minus1;
yading@11 1198 if (c->srcBpc < 8)
yading@11 1199 c->srcBpc = 8;
yading@11 1200 c->dstBpc = 1 + desc_dst->comp[0].depth_minus1;
yading@11 1201 if (c->dstBpc < 8)
yading@11 1202 c->dstBpc = 8;
yading@11 1203 if (isAnyRGB(srcFormat) || srcFormat == AV_PIX_FMT_PAL8)
yading@11 1204 c->srcBpc = 16;
yading@11 1205 if (c->dstBpc == 16)
yading@11 1206 dst_stride <<= 1;
yading@11 1207
yading@11 1208 if (INLINE_MMXEXT(cpu_flags) && c->srcBpc == 8 && c->dstBpc <= 14) {
yading@11 1209 c->canMMXEXTBeUsed = (dstW >= srcW && (dstW & 31) == 0 &&
yading@11 1210 (srcW & 15) == 0) ? 1 : 0;
yading@11 1211 if (!c->canMMXEXTBeUsed && dstW >= srcW && (srcW & 15) == 0
yading@11 1212
yading@11 1213 && (flags & SWS_FAST_BILINEAR)) {
yading@11 1214 if (flags & SWS_PRINT_INFO)
yading@11 1215 av_log(c, AV_LOG_INFO,
yading@11 1216 "output width is not a multiple of 32 -> no MMXEXT scaler\n");
yading@11 1217 }
yading@11 1218 if (usesHFilter || isNBPS(c->srcFormat) || is16BPS(c->srcFormat) || isAnyRGB(c->srcFormat))
yading@11 1219 c->canMMXEXTBeUsed = 0;
yading@11 1220 } else
yading@11 1221 c->canMMXEXTBeUsed = 0;
yading@11 1222
yading@11 1223 c->chrXInc = (((int64_t)c->chrSrcW << 16) + (c->chrDstW >> 1)) / c->chrDstW;
yading@11 1224 c->chrYInc = (((int64_t)c->chrSrcH << 16) + (c->chrDstH >> 1)) / c->chrDstH;
yading@11 1225
yading@11 1226 /* Match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src
yading@11 1227 * to pixel n-2 of dst, but only for the FAST_BILINEAR mode otherwise do
yading@11 1228 * correct scaling.
yading@11 1229 * n-2 is the last chrominance sample available.
yading@11 1230 * This is not perfect, but no one should notice the difference, the more
yading@11 1231 * correct variant would be like the vertical one, but that would require
yading@11 1232 * some special code for the first and last pixel */
yading@11 1233 if (flags & SWS_FAST_BILINEAR) {
yading@11 1234 if (c->canMMXEXTBeUsed) {
yading@11 1235 c->lumXInc += 20;
yading@11 1236 c->chrXInc += 20;
yading@11 1237 }
yading@11 1238 // we don't use the x86 asm scaler if MMX is available
yading@11 1239 else if (INLINE_MMX(cpu_flags) && c->dstBpc <= 14) {
yading@11 1240 c->lumXInc = ((int64_t)(srcW - 2) << 16) / (dstW - 2) - 20;
yading@11 1241 c->chrXInc = ((int64_t)(c->chrSrcW - 2) << 16) / (c->chrDstW - 2) - 20;
yading@11 1242 }
yading@11 1243 }
yading@11 1244
yading@11 1245 #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS)
yading@11 1246
yading@11 1247 /* precalculate horizontal scaler filter coefficients */
yading@11 1248 {
yading@11 1249 #if HAVE_MMXEXT_INLINE
yading@11 1250 // can't downscale !!!
yading@11 1251 if (c->canMMXEXTBeUsed && (flags & SWS_FAST_BILINEAR)) {
yading@11 1252 c->lumMmxextFilterCodeSize = init_hscaler_mmxext(dstW, c->lumXInc, NULL,
yading@11 1253 NULL, NULL, 8);
yading@11 1254 c->chrMmxextFilterCodeSize = init_hscaler_mmxext(c->chrDstW, c->chrXInc,
yading@11 1255 NULL, NULL, NULL, 4);
yading@11 1256
yading@11 1257 #if USE_MMAP
yading@11 1258 c->lumMmxextFilterCode = mmap(NULL, c->lumMmxextFilterCodeSize,
yading@11 1259 PROT_READ | PROT_WRITE,
yading@11 1260 MAP_PRIVATE | MAP_ANONYMOUS,
yading@11 1261 -1, 0);
yading@11 1262 c->chrMmxextFilterCode = mmap(NULL, c->chrMmxextFilterCodeSize,
yading@11 1263 PROT_READ | PROT_WRITE,
yading@11 1264 MAP_PRIVATE | MAP_ANONYMOUS,
yading@11 1265 -1, 0);
yading@11 1266 #elif HAVE_VIRTUALALLOC
yading@11 1267 c->lumMmxextFilterCode = VirtualAlloc(NULL,
yading@11 1268 c->lumMmxextFilterCodeSize,
yading@11 1269 MEM_COMMIT,
yading@11 1270 PAGE_EXECUTE_READWRITE);
yading@11 1271 c->chrMmxextFilterCode = VirtualAlloc(NULL,
yading@11 1272 c->chrMmxextFilterCodeSize,
yading@11 1273 MEM_COMMIT,
yading@11 1274 PAGE_EXECUTE_READWRITE);
yading@11 1275 #else
yading@11 1276 c->lumMmxextFilterCode = av_malloc(c->lumMmxextFilterCodeSize);
yading@11 1277 c->chrMmxextFilterCode = av_malloc(c->chrMmxextFilterCodeSize);
yading@11 1278 #endif
yading@11 1279
yading@11 1280 #ifdef MAP_ANONYMOUS
yading@11 1281 if (c->lumMmxextFilterCode == MAP_FAILED || c->chrMmxextFilterCode == MAP_FAILED)
yading@11 1282 #else
yading@11 1283 if (!c->lumMmxextFilterCode || !c->chrMmxextFilterCode)
yading@11 1284 #endif
yading@11 1285 {
yading@11 1286 av_log(c, AV_LOG_ERROR, "Failed to allocate MMX2FilterCode\n");
yading@11 1287 return AVERROR(ENOMEM);
yading@11 1288 }
yading@11 1289
yading@11 1290 FF_ALLOCZ_OR_GOTO(c, c->hLumFilter, (dstW / 8 + 8) * sizeof(int16_t), fail);
yading@11 1291 FF_ALLOCZ_OR_GOTO(c, c->hChrFilter, (c->chrDstW / 4 + 8) * sizeof(int16_t), fail);
yading@11 1292 FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW / 2 / 8 + 8) * sizeof(int32_t), fail);
yading@11 1293 FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW / 2 / 4 + 8) * sizeof(int32_t), fail);
yading@11 1294
yading@11 1295 init_hscaler_mmxext( dstW, c->lumXInc, c->lumMmxextFilterCode,
yading@11 1296 c->hLumFilter, (uint32_t*)c->hLumFilterPos, 8);
yading@11 1297 init_hscaler_mmxext(c->chrDstW, c->chrXInc, c->chrMmxextFilterCode,
yading@11 1298 c->hChrFilter, (uint32_t*)c->hChrFilterPos, 4);
yading@11 1299
yading@11 1300 #if USE_MMAP
yading@11 1301 mprotect(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize, PROT_EXEC | PROT_READ);
yading@11 1302 mprotect(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize, PROT_EXEC | PROT_READ);
yading@11 1303 #endif
yading@11 1304 } else
yading@11 1305 #endif /* HAVE_MMXEXT_INLINE */
yading@11 1306 {
yading@11 1307 const int filterAlign =
yading@11 1308 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 4 :
yading@11 1309 (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
yading@11 1310 1;
yading@11 1311
yading@11 1312 if (initFilter(&c->hLumFilter, &c->hLumFilterPos,
yading@11 1313 &c->hLumFilterSize, c->lumXInc,
yading@11 1314 srcW, dstW, filterAlign, 1 << 14,
yading@11 1315 (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
yading@11 1316 cpu_flags, srcFilter->lumH, dstFilter->lumH,
yading@11 1317 c->param) < 0)
yading@11 1318 goto fail;
yading@11 1319 if (initFilter(&c->hChrFilter, &c->hChrFilterPos,
yading@11 1320 &c->hChrFilterSize, c->chrXInc,
yading@11 1321 c->chrSrcW, c->chrDstW, filterAlign, 1 << 14,
yading@11 1322 (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
yading@11 1323 cpu_flags, srcFilter->chrH, dstFilter->chrH,
yading@11 1324 c->param) < 0)
yading@11 1325 goto fail;
yading@11 1326 }
yading@11 1327 } // initialize horizontal stuff
yading@11 1328
yading@11 1329 /* precalculate vertical scaler filter coefficients */
yading@11 1330 {
yading@11 1331 const int filterAlign =
yading@11 1332 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 2 :
yading@11 1333 (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
yading@11 1334 1;
yading@11 1335
yading@11 1336 if (initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,
yading@11 1337 c->lumYInc, srcH, dstH, filterAlign, (1 << 12),
yading@11 1338 (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
yading@11 1339 cpu_flags, srcFilter->lumV, dstFilter->lumV,
yading@11 1340 c->param) < 0)
yading@11 1341 goto fail;
yading@11 1342 if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize,
yading@11 1343 c->chrYInc, c->chrSrcH, c->chrDstH,
yading@11 1344 filterAlign, (1 << 12),
yading@11 1345 (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
yading@11 1346 cpu_flags, srcFilter->chrV, dstFilter->chrV,
yading@11 1347 c->param) < 0)
yading@11 1348 goto fail;
yading@11 1349
yading@11 1350 #if HAVE_ALTIVEC
yading@11 1351 FF_ALLOC_OR_GOTO(c, c->vYCoeffsBank, sizeof(vector signed short) * c->vLumFilterSize * c->dstH, fail);
yading@11 1352 FF_ALLOC_OR_GOTO(c, c->vCCoeffsBank, sizeof(vector signed short) * c->vChrFilterSize * c->chrDstH, fail);
yading@11 1353
yading@11 1354 for (i = 0; i < c->vLumFilterSize * c->dstH; i++) {
yading@11 1355 int j;
yading@11 1356 short *p = (short *)&c->vYCoeffsBank[i];
yading@11 1357 for (j = 0; j < 8; j++)
yading@11 1358 p[j] = c->vLumFilter[i];
yading@11 1359 }
yading@11 1360
yading@11 1361 for (i = 0; i < c->vChrFilterSize * c->chrDstH; i++) {
yading@11 1362 int j;
yading@11 1363 short *p = (short *)&c->vCCoeffsBank[i];
yading@11 1364 for (j = 0; j < 8; j++)
yading@11 1365 p[j] = c->vChrFilter[i];
yading@11 1366 }
yading@11 1367 #endif
yading@11 1368 }
yading@11 1369
yading@11 1370 // calculate buffer sizes so that they won't run out while handling these damn slices
yading@11 1371 c->vLumBufSize = c->vLumFilterSize;
yading@11 1372 c->vChrBufSize = c->vChrFilterSize;
yading@11 1373 for (i = 0; i < dstH; i++) {
yading@11 1374 int chrI = (int64_t)i * c->chrDstH / dstH;
yading@11 1375 int nextSlice = FFMAX(c->vLumFilterPos[i] + c->vLumFilterSize - 1,
yading@11 1376 ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)
yading@11 1377 << c->chrSrcVSubSample));
yading@11 1378
yading@11 1379 nextSlice >>= c->chrSrcVSubSample;
yading@11 1380 nextSlice <<= c->chrSrcVSubSample;
yading@11 1381 if (c->vLumFilterPos[i] + c->vLumBufSize < nextSlice)
yading@11 1382 c->vLumBufSize = nextSlice - c->vLumFilterPos[i];
yading@11 1383 if (c->vChrFilterPos[chrI] + c->vChrBufSize <
yading@11 1384 (nextSlice >> c->chrSrcVSubSample))
yading@11 1385 c->vChrBufSize = (nextSlice >> c->chrSrcVSubSample) -
yading@11 1386 c->vChrFilterPos[chrI];
yading@11 1387 }
yading@11 1388
yading@11 1389 for (i = 0; i < 4; i++)
yading@11 1390 FF_ALLOCZ_OR_GOTO(c, c->dither_error[i], (c->dstW+2) * sizeof(int), fail);
yading@11 1391
yading@11 1392 /* Allocate pixbufs (we use dynamic allocation because otherwise we would
yading@11 1393 * need to allocate several megabytes to handle all possible cases) */
yading@11 1394 FF_ALLOC_OR_GOTO(c, c->lumPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
yading@11 1395 FF_ALLOC_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
yading@11 1396 FF_ALLOC_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
yading@11 1397 if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))
yading@11 1398 FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
yading@11 1399 /* Note we need at least one pixel more at the end because of the MMX code
yading@11 1400 * (just in case someone wants to replace the 4000/8000). */
yading@11 1401 /* align at 16 bytes for AltiVec */
yading@11 1402 for (i = 0; i < c->vLumBufSize; i++) {
yading@11 1403 FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i + c->vLumBufSize],
yading@11 1404 dst_stride + 16, fail);
yading@11 1405 c->lumPixBuf[i] = c->lumPixBuf[i + c->vLumBufSize];
yading@11 1406 }
yading@11 1407 // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
yading@11 1408 c->uv_off = (dst_stride>>1) + 64 / (c->dstBpc &~ 7);
yading@11 1409 c->uv_offx2 = dst_stride + 16;
yading@11 1410 for (i = 0; i < c->vChrBufSize; i++) {
yading@11 1411 FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i + c->vChrBufSize],
yading@11 1412 dst_stride * 2 + 32, fail);
yading@11 1413 c->chrUPixBuf[i] = c->chrUPixBuf[i + c->vChrBufSize];
yading@11 1414 c->chrVPixBuf[i] = c->chrVPixBuf[i + c->vChrBufSize]
yading@11 1415 = c->chrUPixBuf[i] + (dst_stride >> 1) + 8;
yading@11 1416 }
yading@11 1417 if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
yading@11 1418 for (i = 0; i < c->vLumBufSize; i++) {
yading@11 1419 FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf[i + c->vLumBufSize],
yading@11 1420 dst_stride + 16, fail);
yading@11 1421 c->alpPixBuf[i] = c->alpPixBuf[i + c->vLumBufSize];
yading@11 1422 }
yading@11 1423
yading@11 1424 // try to avoid drawing green stuff between the right end and the stride end
yading@11 1425 for (i = 0; i < c->vChrBufSize; i++)
yading@11 1426 if(desc_dst->comp[0].depth_minus1 == 15){
yading@11 1427 av_assert0(c->dstBpc > 14);
yading@11 1428 for(j=0; j<dst_stride/2+1; j++)
yading@11 1429 ((int32_t*)(c->chrUPixBuf[i]))[j] = 1<<18;
yading@11 1430 } else
yading@11 1431 for(j=0; j<dst_stride+1; j++)
yading@11 1432 ((int16_t*)(c->chrUPixBuf[i]))[j] = 1<<14;
yading@11 1433
yading@11 1434 av_assert0(c->chrDstH <= dstH);
yading@11 1435
yading@11 1436 if (flags & SWS_PRINT_INFO) {
yading@11 1437 if (flags & SWS_FAST_BILINEAR)
yading@11 1438 av_log(c, AV_LOG_INFO, "FAST_BILINEAR scaler, ");
yading@11 1439 else if (flags & SWS_BILINEAR)
yading@11 1440 av_log(c, AV_LOG_INFO, "BILINEAR scaler, ");
yading@11 1441 else if (flags & SWS_BICUBIC)
yading@11 1442 av_log(c, AV_LOG_INFO, "BICUBIC scaler, ");
yading@11 1443 else if (flags & SWS_X)
yading@11 1444 av_log(c, AV_LOG_INFO, "Experimental scaler, ");
yading@11 1445 else if (flags & SWS_POINT)
yading@11 1446 av_log(c, AV_LOG_INFO, "Nearest Neighbor / POINT scaler, ");
yading@11 1447 else if (flags & SWS_AREA)
yading@11 1448 av_log(c, AV_LOG_INFO, "Area Averaging scaler, ");
yading@11 1449 else if (flags & SWS_BICUBLIN)
yading@11 1450 av_log(c, AV_LOG_INFO, "luma BICUBIC / chroma BILINEAR scaler, ");
yading@11 1451 else if (flags & SWS_GAUSS)
yading@11 1452 av_log(c, AV_LOG_INFO, "Gaussian scaler, ");
yading@11 1453 else if (flags & SWS_SINC)
yading@11 1454 av_log(c, AV_LOG_INFO, "Sinc scaler, ");
yading@11 1455 else if (flags & SWS_LANCZOS)
yading@11 1456 av_log(c, AV_LOG_INFO, "Lanczos scaler, ");
yading@11 1457 else if (flags & SWS_SPLINE)
yading@11 1458 av_log(c, AV_LOG_INFO, "Bicubic spline scaler, ");
yading@11 1459 else
yading@11 1460 av_log(c, AV_LOG_INFO, "ehh flags invalid?! ");
yading@11 1461
yading@11 1462 av_log(c, AV_LOG_INFO, "from %s to %s%s ",
yading@11 1463 av_get_pix_fmt_name(srcFormat),
yading@11 1464 #ifdef DITHER1XBPP
yading@11 1465 dstFormat == AV_PIX_FMT_BGR555 || dstFormat == AV_PIX_FMT_BGR565 ||
yading@11 1466 dstFormat == AV_PIX_FMT_RGB444BE || dstFormat == AV_PIX_FMT_RGB444LE ||
yading@11 1467 dstFormat == AV_PIX_FMT_BGR444BE || dstFormat == AV_PIX_FMT_BGR444LE ?
yading@11 1468 "dithered " : "",
yading@11 1469 #else
yading@11 1470 "",
yading@11 1471 #endif
yading@11 1472 av_get_pix_fmt_name(dstFormat));
yading@11 1473
yading@11 1474 if (INLINE_MMXEXT(cpu_flags))
yading@11 1475 av_log(c, AV_LOG_INFO, "using MMXEXT\n");
yading@11 1476 else if (INLINE_AMD3DNOW(cpu_flags))
yading@11 1477 av_log(c, AV_LOG_INFO, "using 3DNOW\n");
yading@11 1478 else if (INLINE_MMX(cpu_flags))
yading@11 1479 av_log(c, AV_LOG_INFO, "using MMX\n");
yading@11 1480 else if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC)
yading@11 1481 av_log(c, AV_LOG_INFO, "using AltiVec\n");
yading@11 1482 else
yading@11 1483 av_log(c, AV_LOG_INFO, "using C\n");
yading@11 1484
yading@11 1485 av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
yading@11 1486 av_log(c, AV_LOG_DEBUG,
yading@11 1487 "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
yading@11 1488 c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);
yading@11 1489 av_log(c, AV_LOG_DEBUG,
yading@11 1490 "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
yading@11 1491 c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH,
yading@11 1492 c->chrXInc, c->chrYInc);
yading@11 1493 }
yading@11 1494
yading@11 1495 c->swScale = ff_getSwsFunc(c);
yading@11 1496 return 0;
yading@11 1497 fail: // FIXME replace things by appropriate error codes
yading@11 1498 return -1;
yading@11 1499 }
yading@11 1500
yading@11 1501 #if FF_API_SWS_GETCONTEXT
yading@11 1502 SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
yading@11 1503 int dstW, int dstH, enum AVPixelFormat dstFormat,
yading@11 1504 int flags, SwsFilter *srcFilter,
yading@11 1505 SwsFilter *dstFilter, const double *param)
yading@11 1506 {
yading@11 1507 SwsContext *c;
yading@11 1508
yading@11 1509 if (!(c = sws_alloc_context()))
yading@11 1510 return NULL;
yading@11 1511
yading@11 1512 c->flags = flags;
yading@11 1513 c->srcW = srcW;
yading@11 1514 c->srcH = srcH;
yading@11 1515 c->dstW = dstW;
yading@11 1516 c->dstH = dstH;
yading@11 1517 c->srcRange = handle_jpeg(&srcFormat);
yading@11 1518 c->dstRange = handle_jpeg(&dstFormat);
yading@11 1519 c->src0Alpha = handle_0alpha(&srcFormat);
yading@11 1520 c->dst0Alpha = handle_0alpha(&dstFormat);
yading@11 1521 c->srcFormat = srcFormat;
yading@11 1522 c->dstFormat = dstFormat;
yading@11 1523
yading@11 1524 if (param) {
yading@11 1525 c->param[0] = param[0];
yading@11 1526 c->param[1] = param[1];
yading@11 1527 }
yading@11 1528 sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange,
yading@11 1529 ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
yading@11 1530 c->dstRange, 0, 1 << 16, 1 << 16);
yading@11 1531
yading@11 1532 if (sws_init_context(c, srcFilter, dstFilter) < 0) {
yading@11 1533 sws_freeContext(c);
yading@11 1534 return NULL;
yading@11 1535 }
yading@11 1536
yading@11 1537 return c;
yading@11 1538 }
yading@11 1539 #endif
yading@11 1540
yading@11 1541 SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
yading@11 1542 float lumaSharpen, float chromaSharpen,
yading@11 1543 float chromaHShift, float chromaVShift,
yading@11 1544 int verbose)
yading@11 1545 {
yading@11 1546 SwsFilter *filter = av_malloc(sizeof(SwsFilter));
yading@11 1547 if (!filter)
yading@11 1548 return NULL;
yading@11 1549
yading@11 1550 if (lumaGBlur != 0.0) {
yading@11 1551 filter->lumH = sws_getGaussianVec(lumaGBlur, 3.0);
yading@11 1552 filter->lumV = sws_getGaussianVec(lumaGBlur, 3.0);
yading@11 1553 } else {
yading@11 1554 filter->lumH = sws_getIdentityVec();
yading@11 1555 filter->lumV = sws_getIdentityVec();
yading@11 1556 }
yading@11 1557
yading@11 1558 if (chromaGBlur != 0.0) {
yading@11 1559 filter->chrH = sws_getGaussianVec(chromaGBlur, 3.0);
yading@11 1560 filter->chrV = sws_getGaussianVec(chromaGBlur, 3.0);
yading@11 1561 } else {
yading@11 1562 filter->chrH = sws_getIdentityVec();
yading@11 1563 filter->chrV = sws_getIdentityVec();
yading@11 1564 }
yading@11 1565
yading@11 1566 if (chromaSharpen != 0.0) {
yading@11 1567 SwsVector *id = sws_getIdentityVec();
yading@11 1568 sws_scaleVec(filter->chrH, -chromaSharpen);
yading@11 1569 sws_scaleVec(filter->chrV, -chromaSharpen);
yading@11 1570 sws_addVec(filter->chrH, id);
yading@11 1571 sws_addVec(filter->chrV, id);
yading@11 1572 sws_freeVec(id);
yading@11 1573 }
yading@11 1574
yading@11 1575 if (lumaSharpen != 0.0) {
yading@11 1576 SwsVector *id = sws_getIdentityVec();
yading@11 1577 sws_scaleVec(filter->lumH, -lumaSharpen);
yading@11 1578 sws_scaleVec(filter->lumV, -lumaSharpen);
yading@11 1579 sws_addVec(filter->lumH, id);
yading@11 1580 sws_addVec(filter->lumV, id);
yading@11 1581 sws_freeVec(id);
yading@11 1582 }
yading@11 1583
yading@11 1584 if (chromaHShift != 0.0)
yading@11 1585 sws_shiftVec(filter->chrH, (int)(chromaHShift + 0.5));
yading@11 1586
yading@11 1587 if (chromaVShift != 0.0)
yading@11 1588 sws_shiftVec(filter->chrV, (int)(chromaVShift + 0.5));
yading@11 1589
yading@11 1590 sws_normalizeVec(filter->chrH, 1.0);
yading@11 1591 sws_normalizeVec(filter->chrV, 1.0);
yading@11 1592 sws_normalizeVec(filter->lumH, 1.0);
yading@11 1593 sws_normalizeVec(filter->lumV, 1.0);
yading@11 1594
yading@11 1595 if (verbose)
yading@11 1596 sws_printVec2(filter->chrH, NULL, AV_LOG_DEBUG);
yading@11 1597 if (verbose)
yading@11 1598 sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG);
yading@11 1599
yading@11 1600 return filter;
yading@11 1601 }
yading@11 1602
yading@11 1603 SwsVector *sws_allocVec(int length)
yading@11 1604 {
yading@11 1605 SwsVector *vec;
yading@11 1606
yading@11 1607 if(length <= 0 || length > INT_MAX/ sizeof(double))
yading@11 1608 return NULL;
yading@11 1609
yading@11 1610 vec = av_malloc(sizeof(SwsVector));
yading@11 1611 if (!vec)
yading@11 1612 return NULL;
yading@11 1613 vec->length = length;
yading@11 1614 vec->coeff = av_malloc(sizeof(double) * length);
yading@11 1615 if (!vec->coeff)
yading@11 1616 av_freep(&vec);
yading@11 1617 return vec;
yading@11 1618 }
yading@11 1619
yading@11 1620 SwsVector *sws_getGaussianVec(double variance, double quality)
yading@11 1621 {
yading@11 1622 const int length = (int)(variance * quality + 0.5) | 1;
yading@11 1623 int i;
yading@11 1624 double middle = (length - 1) * 0.5;
yading@11 1625 SwsVector *vec;
yading@11 1626
yading@11 1627 if(variance < 0 || quality < 0)
yading@11 1628 return NULL;
yading@11 1629
yading@11 1630 vec = sws_allocVec(length);
yading@11 1631
yading@11 1632 if (!vec)
yading@11 1633 return NULL;
yading@11 1634
yading@11 1635 for (i = 0; i < length; i++) {
yading@11 1636 double dist = i - middle;
yading@11 1637 vec->coeff[i] = exp(-dist * dist / (2 * variance * variance)) /
yading@11 1638 sqrt(2 * variance * M_PI);
yading@11 1639 }
yading@11 1640
yading@11 1641 sws_normalizeVec(vec, 1.0);
yading@11 1642
yading@11 1643 return vec;
yading@11 1644 }
yading@11 1645
yading@11 1646 SwsVector *sws_getConstVec(double c, int length)
yading@11 1647 {
yading@11 1648 int i;
yading@11 1649 SwsVector *vec = sws_allocVec(length);
yading@11 1650
yading@11 1651 if (!vec)
yading@11 1652 return NULL;
yading@11 1653
yading@11 1654 for (i = 0; i < length; i++)
yading@11 1655 vec->coeff[i] = c;
yading@11 1656
yading@11 1657 return vec;
yading@11 1658 }
yading@11 1659
yading@11 1660 SwsVector *sws_getIdentityVec(void)
yading@11 1661 {
yading@11 1662 return sws_getConstVec(1.0, 1);
yading@11 1663 }
yading@11 1664
yading@11 1665 static double sws_dcVec(SwsVector *a)
yading@11 1666 {
yading@11 1667 int i;
yading@11 1668 double sum = 0;
yading@11 1669
yading@11 1670 for (i = 0; i < a->length; i++)
yading@11 1671 sum += a->coeff[i];
yading@11 1672
yading@11 1673 return sum;
yading@11 1674 }
yading@11 1675
yading@11 1676 void sws_scaleVec(SwsVector *a, double scalar)
yading@11 1677 {
yading@11 1678 int i;
yading@11 1679
yading@11 1680 for (i = 0; i < a->length; i++)
yading@11 1681 a->coeff[i] *= scalar;
yading@11 1682 }
yading@11 1683
yading@11 1684 void sws_normalizeVec(SwsVector *a, double height)
yading@11 1685 {
yading@11 1686 sws_scaleVec(a, height / sws_dcVec(a));
yading@11 1687 }
yading@11 1688
yading@11 1689 static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b)
yading@11 1690 {
yading@11 1691 int length = a->length + b->length - 1;
yading@11 1692 int i, j;
yading@11 1693 SwsVector *vec = sws_getConstVec(0.0, length);
yading@11 1694
yading@11 1695 if (!vec)
yading@11 1696 return NULL;
yading@11 1697
yading@11 1698 for (i = 0; i < a->length; i++) {
yading@11 1699 for (j = 0; j < b->length; j++) {
yading@11 1700 vec->coeff[i + j] += a->coeff[i] * b->coeff[j];
yading@11 1701 }
yading@11 1702 }
yading@11 1703
yading@11 1704 return vec;
yading@11 1705 }
yading@11 1706
yading@11 1707 static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b)
yading@11 1708 {
yading@11 1709 int length = FFMAX(a->length, b->length);
yading@11 1710 int i;
yading@11 1711 SwsVector *vec = sws_getConstVec(0.0, length);
yading@11 1712
yading@11 1713 if (!vec)
yading@11 1714 return NULL;
yading@11 1715
yading@11 1716 for (i = 0; i < a->length; i++)
yading@11 1717 vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
yading@11 1718 for (i = 0; i < b->length; i++)
yading@11 1719 vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] += b->coeff[i];
yading@11 1720
yading@11 1721 return vec;
yading@11 1722 }
yading@11 1723
yading@11 1724 static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b)
yading@11 1725 {
yading@11 1726 int length = FFMAX(a->length, b->length);
yading@11 1727 int i;
yading@11 1728 SwsVector *vec = sws_getConstVec(0.0, length);
yading@11 1729
yading@11 1730 if (!vec)
yading@11 1731 return NULL;
yading@11 1732
yading@11 1733 for (i = 0; i < a->length; i++)
yading@11 1734 vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
yading@11 1735 for (i = 0; i < b->length; i++)
yading@11 1736 vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] -= b->coeff[i];
yading@11 1737
yading@11 1738 return vec;
yading@11 1739 }
yading@11 1740
yading@11 1741 /* shift left / or right if "shift" is negative */
yading@11 1742 static SwsVector *sws_getShiftedVec(SwsVector *a, int shift)
yading@11 1743 {
yading@11 1744 int length = a->length + FFABS(shift) * 2;
yading@11 1745 int i;
yading@11 1746 SwsVector *vec = sws_getConstVec(0.0, length);
yading@11 1747
yading@11 1748 if (!vec)
yading@11 1749 return NULL;
yading@11 1750
yading@11 1751 for (i = 0; i < a->length; i++) {
yading@11 1752 vec->coeff[i + (length - 1) / 2 -
yading@11 1753 (a->length - 1) / 2 - shift] = a->coeff[i];
yading@11 1754 }
yading@11 1755
yading@11 1756 return vec;
yading@11 1757 }
yading@11 1758
yading@11 1759 void sws_shiftVec(SwsVector *a, int shift)
yading@11 1760 {
yading@11 1761 SwsVector *shifted = sws_getShiftedVec(a, shift);
yading@11 1762 av_free(a->coeff);
yading@11 1763 a->coeff = shifted->coeff;
yading@11 1764 a->length = shifted->length;
yading@11 1765 av_free(shifted);
yading@11 1766 }
yading@11 1767
yading@11 1768 void sws_addVec(SwsVector *a, SwsVector *b)
yading@11 1769 {
yading@11 1770 SwsVector *sum = sws_sumVec(a, b);
yading@11 1771 av_free(a->coeff);
yading@11 1772 a->coeff = sum->coeff;
yading@11 1773 a->length = sum->length;
yading@11 1774 av_free(sum);
yading@11 1775 }
yading@11 1776
yading@11 1777 void sws_subVec(SwsVector *a, SwsVector *b)
yading@11 1778 {
yading@11 1779 SwsVector *diff = sws_diffVec(a, b);
yading@11 1780 av_free(a->coeff);
yading@11 1781 a->coeff = diff->coeff;
yading@11 1782 a->length = diff->length;
yading@11 1783 av_free(diff);
yading@11 1784 }
yading@11 1785
yading@11 1786 void sws_convVec(SwsVector *a, SwsVector *b)
yading@11 1787 {
yading@11 1788 SwsVector *conv = sws_getConvVec(a, b);
yading@11 1789 av_free(a->coeff);
yading@11 1790 a->coeff = conv->coeff;
yading@11 1791 a->length = conv->length;
yading@11 1792 av_free(conv);
yading@11 1793 }
yading@11 1794
yading@11 1795 SwsVector *sws_cloneVec(SwsVector *a)
yading@11 1796 {
yading@11 1797 int i;
yading@11 1798 SwsVector *vec = sws_allocVec(a->length);
yading@11 1799
yading@11 1800 if (!vec)
yading@11 1801 return NULL;
yading@11 1802
yading@11 1803 for (i = 0; i < a->length; i++)
yading@11 1804 vec->coeff[i] = a->coeff[i];
yading@11 1805
yading@11 1806 return vec;
yading@11 1807 }
yading@11 1808
yading@11 1809 void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level)
yading@11 1810 {
yading@11 1811 int i;
yading@11 1812 double max = 0;
yading@11 1813 double min = 0;
yading@11 1814 double range;
yading@11 1815
yading@11 1816 for (i = 0; i < a->length; i++)
yading@11 1817 if (a->coeff[i] > max)
yading@11 1818 max = a->coeff[i];
yading@11 1819
yading@11 1820 for (i = 0; i < a->length; i++)
yading@11 1821 if (a->coeff[i] < min)
yading@11 1822 min = a->coeff[i];
yading@11 1823
yading@11 1824 range = max - min;
yading@11 1825
yading@11 1826 for (i = 0; i < a->length; i++) {
yading@11 1827 int x = (int)((a->coeff[i] - min) * 60.0 / range + 0.5);
yading@11 1828 av_log(log_ctx, log_level, "%1.3f ", a->coeff[i]);
yading@11 1829 for (; x > 0; x--)
yading@11 1830 av_log(log_ctx, log_level, " ");
yading@11 1831 av_log(log_ctx, log_level, "|\n");
yading@11 1832 }
yading@11 1833 }
yading@11 1834
yading@11 1835 void sws_freeVec(SwsVector *a)
yading@11 1836 {
yading@11 1837 if (!a)
yading@11 1838 return;
yading@11 1839 av_freep(&a->coeff);
yading@11 1840 a->length = 0;
yading@11 1841 av_free(a);
yading@11 1842 }
yading@11 1843
yading@11 1844 void sws_freeFilter(SwsFilter *filter)
yading@11 1845 {
yading@11 1846 if (!filter)
yading@11 1847 return;
yading@11 1848
yading@11 1849 if (filter->lumH)
yading@11 1850 sws_freeVec(filter->lumH);
yading@11 1851 if (filter->lumV)
yading@11 1852 sws_freeVec(filter->lumV);
yading@11 1853 if (filter->chrH)
yading@11 1854 sws_freeVec(filter->chrH);
yading@11 1855 if (filter->chrV)
yading@11 1856 sws_freeVec(filter->chrV);
yading@11 1857 av_free(filter);
yading@11 1858 }
yading@11 1859
yading@11 1860 void sws_freeContext(SwsContext *c)
yading@11 1861 {
yading@11 1862 int i;
yading@11 1863 if (!c)
yading@11 1864 return;
yading@11 1865
yading@11 1866 if (c->lumPixBuf) {
yading@11 1867 for (i = 0; i < c->vLumBufSize; i++)
yading@11 1868 av_freep(&c->lumPixBuf[i]);
yading@11 1869 av_freep(&c->lumPixBuf);
yading@11 1870 }
yading@11 1871
yading@11 1872 if (c->chrUPixBuf) {
yading@11 1873 for (i = 0; i < c->vChrBufSize; i++)
yading@11 1874 av_freep(&c->chrUPixBuf[i]);
yading@11 1875 av_freep(&c->chrUPixBuf);
yading@11 1876 av_freep(&c->chrVPixBuf);
yading@11 1877 }
yading@11 1878
yading@11 1879 if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
yading@11 1880 for (i = 0; i < c->vLumBufSize; i++)
yading@11 1881 av_freep(&c->alpPixBuf[i]);
yading@11 1882 av_freep(&c->alpPixBuf);
yading@11 1883 }
yading@11 1884
yading@11 1885 for (i = 0; i < 4; i++)
yading@11 1886 av_freep(&c->dither_error[i]);
yading@11 1887
yading@11 1888 av_freep(&c->vLumFilter);
yading@11 1889 av_freep(&c->vChrFilter);
yading@11 1890 av_freep(&c->hLumFilter);
yading@11 1891 av_freep(&c->hChrFilter);
yading@11 1892 #if HAVE_ALTIVEC
yading@11 1893 av_freep(&c->vYCoeffsBank);
yading@11 1894 av_freep(&c->vCCoeffsBank);
yading@11 1895 #endif
yading@11 1896
yading@11 1897 av_freep(&c->vLumFilterPos);
yading@11 1898 av_freep(&c->vChrFilterPos);
yading@11 1899 av_freep(&c->hLumFilterPos);
yading@11 1900 av_freep(&c->hChrFilterPos);
yading@11 1901
yading@11 1902 #if HAVE_MMX_INLINE
yading@11 1903 #if USE_MMAP
yading@11 1904 if (c->lumMmxextFilterCode)
yading@11 1905 munmap(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize);
yading@11 1906 if (c->chrMmxextFilterCode)
yading@11 1907 munmap(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize);
yading@11 1908 #elif HAVE_VIRTUALALLOC
yading@11 1909 if (c->lumMmxextFilterCode)
yading@11 1910 VirtualFree(c->lumMmxextFilterCode, 0, MEM_RELEASE);
yading@11 1911 if (c->chrMmxextFilterCode)
yading@11 1912 VirtualFree(c->chrMmxextFilterCode, 0, MEM_RELEASE);
yading@11 1913 #else
yading@11 1914 av_free(c->lumMmxextFilterCode);
yading@11 1915 av_free(c->chrMmxextFilterCode);
yading@11 1916 #endif
yading@11 1917 c->lumMmxextFilterCode = NULL;
yading@11 1918 c->chrMmxextFilterCode = NULL;
yading@11 1919 #endif /* HAVE_MMX_INLINE */
yading@11 1920
yading@11 1921 av_freep(&c->yuvTable);
yading@11 1922 av_freep(&c->formatConvBuffer);
yading@11 1923
yading@11 1924 av_free(c);
yading@11 1925 }
yading@11 1926
yading@11 1927 struct SwsContext *sws_getCachedContext(struct SwsContext *context, int srcW,
yading@11 1928 int srcH, enum AVPixelFormat srcFormat,
yading@11 1929 int dstW, int dstH,
yading@11 1930 enum AVPixelFormat dstFormat, int flags,
yading@11 1931 SwsFilter *srcFilter,
yading@11 1932 SwsFilter *dstFilter,
yading@11 1933 const double *param)
yading@11 1934 {
yading@11 1935 static const double default_param[2] = { SWS_PARAM_DEFAULT,
yading@11 1936 SWS_PARAM_DEFAULT };
yading@11 1937
yading@11 1938 if (!param)
yading@11 1939 param = default_param;
yading@11 1940
yading@11 1941 if (context &&
yading@11 1942 (context->srcW != srcW ||
yading@11 1943 context->srcH != srcH ||
yading@11 1944 context->srcFormat != srcFormat ||
yading@11 1945 context->dstW != dstW ||
yading@11 1946 context->dstH != dstH ||
yading@11 1947 context->dstFormat != dstFormat ||
yading@11 1948 context->flags != flags ||
yading@11 1949 context->param[0] != param[0] ||
yading@11 1950 context->param[1] != param[1])) {
yading@11 1951 sws_freeContext(context);
yading@11 1952 context = NULL;
yading@11 1953 }
yading@11 1954
yading@11 1955 if (!context) {
yading@11 1956 if (!(context = sws_alloc_context()))
yading@11 1957 return NULL;
yading@11 1958 context->srcW = srcW;
yading@11 1959 context->srcH = srcH;
yading@11 1960 context->srcRange = handle_jpeg(&srcFormat);
yading@11 1961 context->src0Alpha = handle_0alpha(&srcFormat);
yading@11 1962 context->srcFormat = srcFormat;
yading@11 1963 context->dstW = dstW;
yading@11 1964 context->dstH = dstH;
yading@11 1965 context->dstRange = handle_jpeg(&dstFormat);
yading@11 1966 context->dst0Alpha = handle_0alpha(&dstFormat);
yading@11 1967 context->dstFormat = dstFormat;
yading@11 1968 context->flags = flags;
yading@11 1969 context->param[0] = param[0];
yading@11 1970 context->param[1] = param[1];
yading@11 1971 sws_setColorspaceDetails(context, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
yading@11 1972 context->srcRange,
yading@11 1973 ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
yading@11 1974 context->dstRange, 0, 1 << 16, 1 << 16);
yading@11 1975 if (sws_init_context(context, srcFilter, dstFilter) < 0) {
yading@11 1976 sws_freeContext(context);
yading@11 1977 return NULL;
yading@11 1978 }
yading@11 1979 }
yading@11 1980 return context;
yading@11 1981 }